23個最有用的Elasticseaerch檢索技巧(下)

前言

本文主要介紹 Elasticsearch 23種最有用的檢索技巧,提供了詳盡的源碼舉例,並配有相應的Java API實現,是不可多得的 Elasticsearch 學習&實戰資料javascript

注:因爲公衆號推送每篇文章最多 5w 字,因此原文分爲兩篇分別推送,本文爲第二篇  
測試使用的ES版本爲6.3.2java

十二、Term/Terms檢索(指定字段檢索)

上面1-11小節的例子是全文搜索的例子。 有時咱們對結構化搜索更感興趣,咱們但願在其中找到徹底匹配並返回結果git

在下面的例子中,咱們搜索 Manning Publications 發佈的索引中的全部圖書(藉助 term和terms查詢 )github

GET bookdb_index/book/_search
{
  "query": {
    "term": {
      "publisher": {
        "value""manning"
      }
    }
  },
  "_source" : ["title","publish_date","publisher"]
}

[Results]
  "hits": {
    "total"3,
    "max_score"0.35667494,
    "hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""2",
        "_score"0.35667494,
        "_source": {
          "publisher""manning",
          "title""Taming Text: How to Find, Organize, and Manipulate It",
          "publish_date""2013-01-24"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""3",
        "_score"0.35667494,
        "_source": {
          "publisher""manning",
          "title""Elasticsearch in Action",
          "publish_date""2015-12-03"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""4",
        "_score"0.35667494,
        "_source": {
          "publisher""manning",
          "title""Solr in Action",
          "publish_date""2014-04-05"
        }
      }
    ]
  }

Multiple terms可指定多個關鍵詞進行檢索緩存

GET bookdb_index/book/_search
{
  "query": {
    "terms": {
      "publisher": ["oreilly""manning"]
    }
  }
}

1三、Term排序檢索-(Term Query - Sorted)

Term查詢和其餘查詢同樣,輕鬆的實現排序。多級排序也是容許的服務器

GET bookdb_index/book/_search
{
  "query": {
    "term": {
      "publisher": {
        "value""manning"
      }
    }
  },
  "_source" : ["title","publish_date","publisher"],
  "sort": [{"publisher.keyword": { "order""desc"}},
    {"title.keyword": {"order""asc"}}]
}

[Results]
  "hits": {
    "total"3,
    "max_score"null,
    "hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""3",
        "_score"null,
        "_source": {
          "publisher""manning",
          "title""Elasticsearch in Action",
          "publish_date""2015-12-03"
        },
        "sort": [
          "manning",
          "Elasticsearch in Action"
        ]
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""4",
        "_score"null,
        "_source": {
          "publisher""manning",
          "title""Solr in Action",
          "publish_date""2014-04-05"
        },
        "sort": [
          "manning",
          "Solr in Action"
        ]
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""2",
        "_score"null,
        "_source": {
          "publisher""manning",
          "title""Taming Text: How to Find, Organize, and Manipulate It",
          "publish_date""2013-01-24"
        },
        "sort": [
          "manning",
          "Taming Text: How to Find, Organize, and Manipulate It"
        ]
      }
    ]
  }

注意:Elasticsearch 6.x 全文搜索用text類型的字段,排序用 number, date 或 keyword 等類型的字段微信

1四、範圍檢索(Range query)

另外一個結構化檢索的例子是範圍檢索。下面的舉例中,咱們檢索了2015年發佈的書籍。app

GET bookdb_index/book/_search
{
  "query": {
    "range": {
      "publish_date": {
        "gte""2015-01-01",
        "lte""2015-12-31"
      }
    }
  },
  "_source" : ["title","publish_date","publisher"]
}

[Results]
  "hits": {
    "total"2,
    "max_score"1,
    "hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""1",
        "_score"1,
        "_source": {
          "publisher""oreilly",
          "title""Elasticsearch: The Definitive Guide",
          "publish_date""2015-02-07"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""3",
        "_score"1,
        "_source": {
          "publisher""manning",
          "title""Elasticsearch in Action",
          "publish_date""2015-12-03"
        }
      }
    ]
  }

注意:範圍查詢適用於日期,數字和字符串類型字段elasticsearch

1五、過濾檢索(Filtered query)

(5.0版本起已再也不存在,沒必要關注)ide

過濾的查詢容許您過濾查詢的結果。    以下的例子,咱們在標題或摘要中查詢名爲「Elasticsearch」的圖書,可是咱們但願將結果過濾到只有20個或更多評論的結果。

POST /bookdb_index/book/_search
{
    "query": {
        "filtered": {
            "query" : {
                "multi_match": {
                    "query""elasticsearch",
                    "fields": ["title","summary"]
                }
            },
            "filter": {
                "range" : {
                    "num_reviews": {
                        "gte"20
                    }
                }
            }
        }
    },
    "_source" : ["title","summary","publisher""num_reviews"]
}


[Results]
"hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""1",
        "_score"0.5955761,
        "_source": {
          "summary""A distibuted real-time search and analytics engine",
          "publisher""oreilly",
          "num_reviews"20,
          "title""Elasticsearch: The Definitive Guide"
        }
      }
    ]

注意:已過濾的查詢不要求存在要過濾的查詢。 若是沒有指定查詢,則運行 match_all 查詢,基本上返回索引中的全部文檔,而後對其進行過濾。
實際上,首先運行過濾器,減小須要查詢的表面積。 此外,過濾器在第一次使用後被緩存,這使得它很是有效

更新: 已篩選的查詢已推出的Elasticsearch 5.X版本中移除,有利於布爾查詢。 這是與上面重寫的使用bool查詢相同的示例。 返回的結果是徹底同樣的。

GET bookdb_index/book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query""elasticsearch",
            "fields": ["title","summary"]
          }
        }
      ],
      "filter": {
        "range": {
          "num_reviews": {
            "gte"20
          }
        }
      }
    }
  },
  "_source" : ["title","summary","publisher""num_reviews"]
}

1六、多個過濾器檢索(Multiple Filters)

(5.x再也不支持,無需關注)
多個過濾器能夠經過使用布爾過濾器進行組合。

在下一個示例中,過濾器肯定返回的結果必須至少包含20個評論,不得在2015年以前發佈,而且應該由oreilly發佈

POST /bookdb_index/book/_search
{
    "query": {
        "filtered": {
            "query" : {
                "multi_match": {
                    "query""elasticsearch",
                    "fields": ["title","summary"]
                }
            },
            "filter": {
                "bool": {
                    "must": {
                        "range" : { "num_reviews": { "gte"20 } }
                    },
                    "must_not": {
                        "range" : { "publish_date": { "lte""2014-12-31" } }
                    },
                    "should": {
                        "term": { "publisher""oreilly" }
                    }
                }
            }
        }
    },
    "_source" : ["title","summary","publisher""num_reviews""publish_date"]
}


[Results]
"hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""1",
        "_score"0.5955761,
        "_source": {
          "summary""A distibuted real-time search and analytics engine",
          "publisher""oreilly",
          "num_reviews"20,
          "title""Elasticsearch: The Definitive Guide",
          "publish_date""2015-02-07"
        }
      }
    ]

1七、 Function 得分:Field值因子( Function Score: Field Value Factor)

可能有一種狀況,您想要將文檔中特定字段的值歸入相關性分數的計算。 這在您但願基於其受歡迎程度提高文檔的相關性的狀況下是有表明性的場景

在咱們的例子中,咱們但願增長更受歡迎的書籍(按評論數量判斷)。 這可使用field_value_factor函數得分

GET bookdb_index/book/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query""search engine",
          "fields": ["title","summary"]
        }
      },
      "field_value_factor": {
        "field""num_reviews",
        "modifier""log1p",
        "factor"2
      }
    }
  },
  "_source": ["title""summary""publish_date""num_reviews"]
}

[Results]
    "hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""1",
        "_score"1.5694137,
        "_source": {
          "summary""A distibuted real-time search and analytics engine",
          "num_reviews"20,
          "title""Elasticsearch: The Definitive Guide",
          "publish_date""2015-02-07"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""4",
        "_score"1.4725765,
        "_source": {
          "summary""Comprehensive guide to implementing a scalable search engine using Apache Solr",
          "num_reviews"23,
          "title""Solr in Action",
          "publish_date""2014-04-05"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""3",
        "_score"0.14181662,
        "_source": {
          "summary""build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms",
          "num_reviews"18,
          "title""Elasticsearch in Action",
          "publish_date""2015-12-03"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""2",
        "_score"0.13297246,
        "_source": {
          "summary""organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization",
          "num_reviews"12,
          "title""Taming Text: How to Find, Organize, and Manipulate It",
          "publish_date""2013-01-24"
        }
      }
    ]
  }

注1:咱們能夠運行一個常規的multi_match查詢,並按num_reviews字段排序,可是咱們失去了相關性得分的好處。  
注2:有許多附加參數能夠調整對原始相關性分數
(如「 modifier 」,「 factor 」,「boost_mode」等)的加強效果的程度。  
詳見 Elasticsearch guide.

1八、 Function 得分:衰減函數( Function Score: Decay Functions )

假設,咱們不是想經過一個字段的值逐漸增長得分,以獲取理想的結果。    舉例:價格範圍、數字字段範圍、日期範圍。 在咱們的例子中,咱們正在搜索2014年6月左右出版的「 search engines 」的書籍。

GET bookdb_index/book/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query""search engine",
          "fields": ["title""summary"]
        }
      },
      "functions": [
        {
          "exp": {
            "publish_date": {
              "origin""2014-06-15",
              "scale""30d",
              "offset""7d"
            }
          }
        }
      ],
      "boost_mode""replace"
    }
  },
  "_source": ["title""summary""publish_date""num_reviews"]
}

[Results]
  "hits": {
    "total"4,
    "max_score"0.22793062,
    "hits": [
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""4",
        "_score"0.22793062,
        "_source": {
          "summary""Comprehensive guide to implementing a scalable search engine using Apache Solr",
          "num_reviews"23,
          "title""Solr in Action",
          "publish_date""2014-04-05"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""1",
        "_score"0.0049215667,
        "_source": {
          "summary""A distibuted real-time search and analytics engine",
          "num_reviews"20,
          "title""Elasticsearch: The Definitive Guide",
          "publish_date""2015-02-07"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""2",
        "_score"0.000009612435,
        "_source": {
          "summary""organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization",
          "num_reviews"12,
          "title""Taming Text: How to Find, Organize, and Manipulate It",
          "publish_date""2013-01-24"
        }
      },
      {
        "_index""bookdb_index",
        "_type""book",
        "_id""3",
        "_score"0.0000049185574,
        "_source": {
          "summary""build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms",
          "num_reviews"18,
          "title""Elasticsearch in Action",
          "publish_date""2015-12-03"
        }
      }
    ]
  }

1九、Function得分:腳本得分( Function Score: Script Scoring )

在內置計分功能不符合您需求的狀況下,能夠選擇指定用於評分的Groovy腳本

在咱們的示例中,咱們要指定一個考慮到publish_date的腳本,而後再決定考慮多少評論。 較新的書籍可能沒有這麼多的評論,因此他們不該該爲此付出「代價」

得分腳本以下所示:

publish_date = doc['publish_date'].value
num_reviews = doc['num_reviews'].value

if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) {
  my_score = Math.log(2.5 + num_reviews)
else {
  my_score = Math.log(1 + num_reviews)
}
return my_score

要動態使用評分腳本,咱們使用script_score參數

GET /bookdb_index/book/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query""search engine",
          "fields": ["title","summary"]
        }
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "params": {
                "threshold""2015-07-30"
              },  
              "lang""groovy"
              "source""publish_date = doc['publish_date'].value; num_reviews = doc['num_reviews'].value; if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) { return log(2.5 + num_reviews) }; return log(1 + num_reviews);"
            }
          }
        }
      ]
    }
  },
  "_source": ["title","summary","publish_date""num_reviews"]
}

注1:要使用動態腳本,必須爲config / elasticsearch.yml文件中的Elasticsearch實例啓用它。 也可使用已經存儲在Elasticsearch服務器上的腳本。 查看 Elasticsearch reference docs 以獲取更多信息。    
注2: JSON不能包含嵌入的換行符,所以分號用於分隔語句。  
原文做者: by Tim Ojo Aug. 05, 16 · Big Data Zone    
原文地址:https://dzone.com/articles/23-useful-elasticsearch-example-queries

注意:ES6.3 怎樣啓用 groovy 腳本?配置未成功  
script.allowed_types: inline  & script.allowed_contexts: search, update

Java API 實現

Java API 實現上面的查詢,代碼見 https://github.com/whirlys/elastic-example/tree/master/UsefullESSearchSkill

注:Java API 實現仍在測試中,儘快上傳


更多內容請訪問個人我的博客:http://laijianfeng.org
參考文章:  
銘毅天下:[譯]你必須知道的23個最有用的Elasticseaerch檢索技巧  
英文原文:23 Useful Elasticsearch Example Queries


本文分享自微信公衆號 - 小旋鋒(whirlysBigData)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索