在我之前的文章文章:
Elasticsearch:有用的 Elasticsearch 查询示例
开始使用 Elasticsearch (2)
我列举了很多关于 Elasticsearch 查询的例子。抱着多多益善的想法,在今天的文章中,我给大家带来更多的例子给大家练习。希望大家对 Elasticsearch 有更多的认识。
Elasticsearch 提供了一组强大的选项来查询各种用例的文档,因此了解将哪个查询应用于特定案例很有用。 以下是一个动手教程,可帮助你利用 Elasticsearch 提供的最重要的查询。
在本指南中,你将学习许多 带有详细解释的流行查询示例。 此处涵盖的每个查询将分为 2 种类型:
结构化查询:用于检索结构化数据的查询,例如日期、数字、密码等。全文查询:用于查询纯文本的查询。
请注意:在本文章中, 我将使用最新的 Elastic Stack 7.16.3 发布来进行展示。有于文章比较长,所以分为两个部分:
Elasticsearch:Elasticsearch 查询示例 - 动手练习(一)Elasticsearch:Elasticsearch 查询示例 - 动手练习(二)
设置演示索引让我们首先使用一些示例数据创建一个新索引,以便你可以按照每个搜索示例进行 *** 作。创建一个名为 “employees” 的索引:
PUT employees
为包含在摄入文档中的字段 (比如,date_of_birth) 定义映射(模式):
PUT employees/_mapping { "properties": { "date_of_birth": { "type": "date", "format": "dd/MM/yyyy" } } }
上面显示,我们文档的日期格式是 dd/MM/yyyy。
现在让我们将一些文档摄入到我们新创建的索引中,如下面的示例所示,使用 Elasticsearch 的 _bulk API:
POST _bulk {"index":{"_index":"employees","_id":"1"}} {"id":1,"name":"Huntlee Dargavel","email":"hdargavel0@japanpost.jp","gender":"male","ip_address":"58.11.89.193","date_of_birth":"11/09/1990","company":"Talane","position":"Research Associate","experience":7,"country":"China","phrase":"Multi-channelled coherent leverage","salary":180025} {"index":{"_index":"employees","_id":"2"}} {"id":2,"name":"Othilia Cathel","email":"ocathel1@senate.gov","gender":"female","ip_address":"3.164.153.228","date_of_birth":"22/07/1987","company":"Edgepulse","position":"Structural Engineer","experience":11,"country":"China","phrase":"Grass-roots heuristic help-desk","salary":193530} {"index":{"_index":"employees","_id":"3"}} {"id":3,"name":"Winston Waren","email":"wwaren2@4shared.com","gender":"male","ip_address":"202.37.210.94","date_of_birth":"10/11/1985","company":"Yozio","position":"Human Resources Manager","experience":12,"country":"China","phrase":"Versatile object-oriented emulation","salary":50616} {"index":{"_index":"employees","_id":"4"}} {"id":4,"name":"Alan Thomas","email":"athomas2@example.com","gender":"male","ip_address":"200.47.210.95","date_of_birth":"11/12/1985","company":"Yamaha","position":"Resources Manager","experience":12,"country":"China","phrase":"Emulation of roots heuristic coherent systems","salary":300000}
现在我们已经有了一个包含文档的索引和一个指定的映射,我们已经准备好开始使用示例搜索了。为方便大家阅读,我把其中的一个文档的字段列出来:
GET employees/_doc/1?filter_path=_source
{ "_source" : { "id" : 1, "name" : "Huntlee Dargavel", "email" : "hdargavel0@japanpost.jp", "gender" : "male", "ip_address" : "58.11.89.193", "date_of_birth" : "11/09/1990", "company" : "Talane", "position" : "Research Associate", "experience" : 7, "country" : "China", "phrase" : "Multi-channelled coherent leverage", "salary" : 180025 } }
从上面的返回数据中,我们可以看到包含在每个文档中的字段。整个索引我们只包含4个文档,但是它足以让我们了解各个搜索。较少的数据集可以让我们看得更加清楚。
Match query“match” 查询 是 Elasticsearch 中最基本、最常用的查询之一,起到全文查询的作用。 我们可以使用这个查询来搜索文本、数字或布尔值。
让我们在之前提取的文档中搜索名为 “phrase” 的字段中包含的单词 “heuristic”。
POST employees/_search { "query": { "match": { "phrase": { "query": "heuristic" } } } }
在我们索引中的 4 个文档中,只有 2 个文档中的 “phrase” 字段中的包含 “heuristic”一词:
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.6785375, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : 0.6785375, "_source" : { "id" : 2, "name" : "Othilia Cathel", "email" : "ocathel1@senate.gov", "gender" : "female", "ip_address" : "3.164.153.228", "date_of_birth" : "22/07/1987", "company" : "Edgepulse", "position" : "Structural Engineer", "experience" : 11, "country" : "China", "phrase" : "Grass-roots heuristic help-desk", "salary" : 193530 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 0.62577873, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }
如果我们要搜索多个单词会发生什么? 使用我们刚刚执行的相同查询,让我们搜索 “heuristic roots help”:
POST employees/_search { "query": { "match": { "phrase": { "query": "heuristic roots help" } } } }
这将返回与以前相同的文档,因为默认情况下,Elasticsearch 使用 OR 运算符处理搜索查询中的每个单词。 在我们的例子中,查询将匹配任何包含 “heuristic” 或 “roots” 或 “help” 的文档。
应用于多词搜索的 OR 运算符是 match 的默认行为,但是我们可以使用与 “match” 查询一起传递的 “operator” 参数来更改。我们可以使用 “OR” 或 “AND” 值指定 operator 参数。
让我们看看当我们在之前执行的同一查询中提供运算符参数 “AND” 时会发生什么。
POST employees/_search { "query": { "match": { "phrase": { "query": "heuristic roots help", "operator": "AND" } } } }
现在结果将只返回一个文档(文档 id=2),因为这是在 “phrase” 字段中同时包含所有三个搜索关键字的唯一文档。
minimum_should_match更进一步,我们可以为文档必须包含的最小匹配词设置一个阈值。 例如,如果我们将此参数设置为 1,则查询将检查至少有 1 个匹配词的任何文档。
现在,如果我们将 “minium_should_match” 参数设置为 3,那么所有三个单词都必须出现在文档中才能被归类为匹配项。
在我们的例子中,以下查询将仅返回 1 个文档(id=2),因为它是唯一符合我们条件的文档:
POST employees/_search { "query": { "match": { "phrase": { "query" : "heuristic roots help", "minimum_should_match": 3 } } } }Mulit-Match Query
到目前为止,我们一直在处理单个字段上的匹配项——也就是说,我们在名为 “phrase” 的单个字段中搜索关键字。但是,如果我们需要在文档的多个字段中搜索关键字怎么办? 这就是多匹配(multi-match)查询发挥作用的地方。
让我们尝试在文档中包含的 “position” 和 “phrase” 字段中搜索关键字 “research help” 的示例。
POST employees/_search { "query": { "multi_match": { "query": "research help", "fields": [ "position", "phrase" ] } } }
这将导致以下响应:
{ "took" : 24, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.2613049, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : 1.2613049, "_source" : { "id" : 1, "name" : "Huntlee Dargavel", "email" : "hdargavel0@japanpost.jp", "gender" : "male", "ip_address" : "58.11.89.193", "date_of_birth" : "11/09/1990", "company" : "Talane", "position" : "Research Associate", "experience" : 7, "country" : "China", "phrase" : "Multi-channelled coherent leverage", "salary" : 180025 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : 1.1785964, "_source" : { "id" : 2, "name" : "Othilia Cathel", "email" : "ocathel1@senate.gov", "gender" : "female", "ip_address" : "3.164.153.228", "date_of_birth" : "22/07/1987", "company" : "Edgepulse", "position" : "Structural Engineer", "experience" : 11, "country" : "China", "phrase" : "Grass-roots heuristic help-desk", "salary" : 193530 } } ] } }
从上面的结果中,我们可以看出来任何在 position 或 phrase 字段包含 research 或者 help 的文档都将被搜索到。
Match PhraseMatch_phrase 是另一种常用的查询,正如其名称所示,它匹配字段中的短语。
如果我们需要在员工索引的 “phrase” 字段中搜索短语 “roots heuristic coherent”,我们可以使用 “match_phrase” 查询:
GET employees/_search { "query": { "match_phrase": { "phrase": { "query": "roots heuristic coherent" } } } }
这将返回具有确切短语 “roots heuristic coherent” 的文档,包括单词的顺序。 在我们的例子中,我们只有一个符合上述条件的结果,如下面的响应所示:
{ "took" : 23, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.877336, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 1.877336, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }slop 参数
我们可以在 match_phrase 查询中使用的一个有用功能是 “slop” 参数,它允许我们创建更灵活的搜索。
假设我们使用 match_phrase 查询搜索 “roots coherent”。 我们不会收到从员工索引返回的任何文档。 这是因为要匹配 match_phrase,这些术语需要按照准确的顺序排列。
现在,让我们使用 slop 参数,看看会发生什么:
GET employees/_search { "query": { "match_phrase": { "phrase": { "query": "roots coherent", "slop": 1 } } } }
当 slop=1 时,查询表明可以移动一个单词进行匹配,因此我们将收到以下响应。 在下面的响应中,你可以看到 “roots coherent” 与 “roots heuristic coherent” 文档相匹配。 这是因为 slop 参数允许跳过 1 个术语。
{ "took" : 3, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.7873249, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 0.7873249, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }Match Phrase Prefix
match_phrase_prefix 查询类似于 match_phrase 查询,但这里将搜索关键字的最后一个词视为前缀,用于匹配以该前缀词开头的任何词。
首先,让我们在索引中插入一个文档,以更好地理解 match_phrase_prefix 查询:
PUT employees/_doc/5 { "id": 4, "name": "Jennifer Lawrence", "email": "jlaw@example.com", "gender": "female", "ip_address": "100.37.110.59", "date_of_birth": "17/05/1995", "company": "Monsnto", "position": "Resources Manager", "experience": 10, "country": "Germany", "phrase": "Emulation of roots heuristic complete systems", "salary": 300000 }
现在让我们应用 match_phrase_prefix:
GET employees/_search { "_source": [ "phrase" ], "query": { "match_phrase_prefix": { "phrase": { "query": "roots heuristic co" } } } }
在下面的结果中,我们可以看到具有 coherent 和 complete 的文档与查询匹配。 我们还可以在 “match_phrase” 查询中使用 slop 参数。
{ "took" : 61, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 3.0871696, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 3.0871696, "_source" : { "phrase" : "Emulation of roots heuristic coherent systems" } }, { "_index" : "employees", "_type" : "_doc", "_id" : "5", "_score" : 3.0871696, "_source" : { "phrase" : "Emulation of roots heuristic complete systems" } } ] } }
注意:“match_phrase_query” 尝试匹配最后提供的关键字(在我们的示例中为 co)的 50 个扩展(默认情况下),也就是说搜索到包含有 co 的50个结果。 这可以通过指定 “max_expansions” 参数来增加或减少。
GET employees/_search { "_source": [ "phrase" ], "query": { "match_phrase_prefix": { "phrase": { "query": "roots heuristic co", "max_expansions": 1 } } } }
比如,上面的查询将只返回一个文档:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.805721, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 1.805721, "_source" : { "phrase" : "Emulation of roots heuristic coherent systems" } } ] } }
由于这个前缀属性和 match_phrase_prefix 查询的易于设置的属性,它通常用于自动完成功能。
现在让我们删除刚刚添加的 id=5 的文档:
DELETE employees/_doc/5Term 级查询
术语级查询用于查询结构化数据,通常是精确值。
Term Query/Terms Query这是最简单的术语级别查询。 此查询针对文档中的字段搜索搜索关键字(keyword)的完全匹配。
例如,如果我们对 “gender” 字段使用术语查询来搜索 “Male” 这个词,它会完全按照这个词进行搜索,即使有大小写也是如此。
这可以通过以下两个查询来证明:
GET employees/_search { "query": { "term": { "gender": { "value": "female" } } } }
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.87546873, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : 0.87546873, "_source" : { "id" : 2, "name" : "Othilia Cathel", "email" : "ocathel1@senate.gov", "gender" : "female", "ip_address" : "3.164.153.228", "date_of_birth" : "22/07/1987", "company" : "Edgepulse", "position" : "Structural Engineer", "experience" : 11, "country" : "China", "phrase" : "Grass-roots heuristic help-desk", "salary" : 193530 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "5", "_score" : 0.87546873, "_source" : { "id" : 4, "name" : "Jennifer Lawrence", "email" : "jlaw@example.com", "gender" : "female", "ip_address" : "100.37.110.59", "date_of_birth" : "17/05/1995", "company" : "Monsnto", "position" : "Resources Manager", "experience" : 10, "country" : "Germany", "phrase" : "Emulation of roots heuristic complete systems", "salary" : 300000 } } ] } }
上面的搜索返回有两个结果。如果我们做如下的查询:
GET employees/_search { "query": { "term": { "gender": { "value": "Female" } } } }
在上面,我们把 female 修改为 Female,那么我们将搜索不到任何的文档。在上述情况下,两个查询之间的唯一区别是搜索关键字的大小写不同。 案例 1 全部为小写,这是匹配的,因为这个字段的值就是按照小写保存的。 但是对于案例 2,搜索没有得到任何结果,因为没有针对带有大写 “F” 的 “gender” 字段的此类 token。
我们还可以使用 terms query 传递多个要在同一字段上搜索的术语。 让我们在性别字段中搜索 “female” 和 “male”。 为此,我们可以使用以下 terms query:
POST employees/_search { "query": { "terms": { "gender": [ "female", "male" ] } } }
上面的查询将返回所有的4个文档。
Exists 查询有时会发生字段没有索引值,或者文档中不存在该字段。 在这种情况下,它有助于识别此类文件并分析影响。
例如,让我们将下面的文档索引到 “employee” 索引
PUT employees/_doc/5 { "id": 5, "name": "Michael Bordon", "email": "mbordon@example.com", "gender": "male", "ip_address": "10.47.210.65", "date_of_birth": "12/12/1995", "position": "Resources Manager", "experience": 12, "country": null, "phrase": "Emulation of roots heuristic coherent systems", "salary": 300000 }
此文档没有名为 “company” 的字段,并且 “country” 字段的值为 null。
现在,如果我们想查找字段为 “company” 的文档,我们可以使用如下的 exist 查询:
GET employees/_search { "query": { "exists": { "field": "company" } } }
上面的查询将列出所有具有 “company” 字段的文档。上面查询的结果将返回4个文档,并且它们都含有 company 字段。而 id=5 的文档不被搜索到。
也许更有用的解决方案是列出所有没有 “company” 字段的文档。 这也可以通过使用如下的存在查询来实现:
GET employees/_search { "query": { "bool": { "must_not": [ { "exists": { "field": "company" } } ] } } }
bool 查询将在以下部分中详细说明。上面的查询将只返回 id=5 的文档:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.0, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "5", "_score" : 0.0, "_source" : { "id" : 5, "name" : "Michael Bordon", "email" : "mbordon@example.com", "gender" : "male", "ip_address" : "10.47.210.65", "date_of_birth" : "12/12/1995", "position" : "Resources Manager", "experience" : 12, "country" : null, "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }
让我们从索引中删除现在插入的文档,为了方便和统一,通过键入以下请求:
DELETE employees/_doc/5Range queries
Elasticsearch 世界中另一个最常用的查询是范围查询。 范围查询允许我们获取包含指定范围内的术语的文档。 范围查询是术语级别的查询(表示用于查询结构化数据),可用于数值字段、日期字段等。
数值字段的 range 查询例如,在我们创建的数据集中,如果我们需要过滤掉 experience 水平在 5 到 10 年之间的人,我们可以对其应用以下范围查询:
POST employees/_search { "query": { "range": { "experience": { "gte": 5, "lte": 10 } } } }
什么是 gte、gt、lt 和 lt?
gte 大于等于,gte: 5 表示大于等于5,其中包括5。greater than or equal togt 大于,gt: 5 ,表示大于5,不包括5。greater thanlte 小于或等于,lte: 5 ,表示小于等于5,其中包括5。less than or equal tolt 小于,less thangt: 5 ,表示小于5,不包括5。 greater than
上面查询的结果为:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "id" : 1, "name" : "Huntlee Dargavel", "email" : "hdargavel0@japanpost.jp", "gender" : "male", "ip_address" : "58.11.89.193", "date_of_birth" : "11/09/1990", "company" : "Talane", "position" : "Research Associate", "experience" : 7, "country" : "China", "phrase" : "Multi-channelled coherent leverage", "salary" : 180025 } } ] } }
也就是说 experience 在 5 和 10 之间的只有一个文档。
日期字段的 range query同样,范围查询也可以应用于日期字段。 如果我们需要找出 1986 年之后出生的人,我们可以发出如下所示的查询:
GET employees/_search { "query": { "range" : { "date_of_birth" : { "gte" : "01/01/1986" } } } }
这将为我们获取仅在 1986 年之后具有 date_of_birth 字段的文档。
Ids queriesids 查询是一个相对较少使用的查询,但它是最有用的查询之一,因此有资格在此列表中。 有时我们需要根据文档的 ID 来检索文档。 这可以使用单个 get 请求来实现,如下所示:
GET indexname/_doc/documentId
如果一个 ID 只能获取一个文档,这可能是一个很好的解决方案,但是如果我们有更多文档怎么办?
这就是 ids 查询非常方便的地方。 使用 Ids 查询,我们可以在单个请求中完成此 *** 作。
在下面的示例中,我们通过单个请求从 employees 索引中获取 id 为 1 和 4 的文档。
POST employees/_search { "query": { "ids" : { "values" : ["1", "4"] } } }
上面查询将返回:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "id" : 1, "name" : "Huntlee Dargavel", "email" : "hdargavel0@japanpost.jp", "gender" : "male", "ip_address" : "58.11.89.193", "date_of_birth" : "11/09/1990", "company" : "Talane", "position" : "Research Associate", "experience" : 7, "country" : "China", "phrase" : "Multi-channelled coherent leverage", "salary" : 180025 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 1.0, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }Prefix Queries
前缀查询(Prefix query)用于获取包含给定搜索字符串作为指定字段前缀的文档。
假设我们需要在 “name” 字段中获取所有包含 “al” 作为前缀的文档,那么我们可以使用前缀查询如下:
GET employees/_search { "query": { "prefix": { "name": "al" } } }
这将导致以下响应:
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 1.0, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }
由于前缀查询是一个术语查询,它将按原样传递搜索字符串。 那就是搜索 “al” 和 “Al” 是不同的。 如果在上面的示例中,我们搜索 “Al”,我们将得到 0 个结果,因为在 “name” 字段的倒排索引中没有以 “Al” 开头的 token。 但是,如果我们查询“name.keyword”字段,使用 “Al” 我们将得到上述结果,在这种情况下,查询 “al” 将导致零命中。
Wildcard quieries这个也叫做通配符查询(wildcard query)。将获取具有与给定通配符模式匹配的术语的文档。例如,让我们在字段 “country” 上使用通配符查询来搜索 “c*a”,如下所示:
GET employees/_search { "query": { "wildcard": { "country": { "value": "c*a" } } } }
上面的查询将获取所有以 “c” 开头并以 “a” 结尾的 “country” 名称的文档(例如:China、Canada、Cambodia 等)。
这里 * 运算符可以匹配零个或多个字符。
Regexp这个是正则查询。这类似于我们上面看到的 “通配符” 查询,但将接受正则表达式作为输入并获取匹配的文档。
GET employees/_search { "query": { "regexp": { "position": "res[a-z]*" } } }
上面的查询将得到匹配正则表达式 res[a-z]* 的单词的文档。
{ "took" : 3, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "id" : 1, "name" : "Huntlee Dargavel", "email" : "hdargavel0@japanpost.jp", "gender" : "male", "ip_address" : "58.11.89.193", "date_of_birth" : "11/09/1990", "company" : "Talane", "position" : "Research Associate", "experience" : 7, "country" : "China", "phrase" : "Multi-channelled coherent leverage", "salary" : 180025 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "3", "_score" : 1.0, "_source" : { "id" : 3, "name" : "Winston Waren", "email" : "wwaren2@4shared.com", "gender" : "male", "ip_address" : "202.37.210.94", "date_of_birth" : "10/11/1985", "company" : "Yozio", "position" : "Human Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Versatile object-oriented emulation", "salary" : 50616 } }, { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : 1.0, "_source" : { "id" : 4, "name" : "Alan Thomas", "email" : "athomas2@example.com", "gender" : "male", "ip_address" : "200.47.210.95", "date_of_birth" : "11/12/1985", "company" : "Yamaha", "position" : "Resources Manager", "experience" : 12, "country" : "China", "phrase" : "Emulation of roots heuristic coherent systems", "salary" : 300000 } } ] } }Fuzzy
模糊查询可用于返回包含与搜索词相似的词的文档。 这在处理拼写错误时尤其有用。即使我们使用模糊查询搜索 “Chnia” 而不是“China”,我们也可以获得结果。
让我们看一个例子:
GET employees/_search { "query": { "fuzzy": { "country": { "value": "Chnia", "fuzziness": "2" } } } }
这里的模糊度是匹配允许的最大编辑距离。 我们在 “match_phrase” 查询中看到的 “max_expansions” 等参数也可以使用。 更多相关文档可以在这里找到
模糊查询也可以与 “match” 查询类型一起出现。 以下示例显示了在 multi_match 查询中使用的模糊性:
POST employees/_search { "query": { "multi_match": { "query": "heursitic reserch", "fields": [ "phrase", "position" ], "fuzziness": 2 } }, "size": 10 }
尽管查询中存在拼写错误,上述查询仍将返回匹配 “heuristic” 或 “research” 的文档。
Boosting在查询时,首先获得更受欢迎的结果通常会有所帮助。 执行此 *** 作的最简单方法在 Elasticsearch 中称为 boosting。 当我们查询多个字段时,这会派上用场。 例如,考虑以下查询:
POST employees/_search { "query": { "multi_match" : { "query" : "versatile Engineer", "fields": ["position^3", "phrase"] } } }
这将返回与 “position” 字段匹配的文档位于顶部的响应,而不是与“phrase”字段匹配的文档。
Sorting - 排序 默认排序当搜索请求中没有指定排序参数时,Elasticsearch 根据 “_score” 字段的降序返回文档。 这个“_score”是根据使用 Elasticsearch 的默认评分方法的查询匹配程度来计算的。 在我们上面讨论的所有示例中,你可以在结果中看到相同的行为。
只有当我们使用 “filter” 上下文时,才不会计算评分,以便更快地返回结果。
Elasticsearch 为我们提供了基于字段进行排序的选项。 比如说,让我们需要根据员工的经验降序对员工进行排序。 我们可以使用启用了排序选项的以下查询来实现:
GET employees/_search { "_source": [ "name", "experience", "salary" ], "sort": [ { "experience": { "order": "desc" } } ] }
上述查询的结果如下:
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 4, "relation" : "eq" }, "max_score" : null, "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "3", "_score" : null, "_source" : { "name" : "Winston Waren", "experience" : 12, "salary" : 50616 }, "sort" : [ 12 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : null, "_source" : { "name" : "Alan Thomas", "experience" : 12, "salary" : 300000 }, "sort" : [ 12 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : null, "_source" : { "name" : "Othilia Cathel", "experience" : 11, "salary" : 193530 }, "sort" : [ 11 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : null, "_source" : { "name" : "Huntlee Dargavel", "experience" : 7, "salary" : 180025 }, "sort" : [ 7 ] } ] } }
从上面的响应中可以看出,结果是根据员工体验的降序排列的。此外,还有两名员工,他们的经验水平与 12 级相同。
如何根据多字段来进行排名在上面的示例中,我们看到有两个员工的经验等级相同,均为 12,但我们需要根据薪水的降序再次排序。 我们也可以提供多个字段进行排序,如下面的查询所示:
GET employees/_search?filter_path=**.hits { "_source": [ "name", "experience", "salary" ], "sort": [ { "experience": { "order": "desc" } }, { "salary": { "order": "desc" } } ] }
现在我们得到以下结果:
{ "hits" : { "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : null, "_source" : { "name" : "Alan Thomas", "experience" : 12, "salary" : 300000 }, "sort" : [ 12, 300000 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "3", "_score" : null, "_source" : { "name" : "Winston Waren", "experience" : 12, "salary" : 50616 }, "sort" : [ 12, 50616 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : null, "_source" : { "name" : "Othilia Cathel", "experience" : 11, "salary" : 193530 }, "sort" : [ 11, 193530 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : null, "_source" : { "name" : "Huntlee Dargavel", "experience" : 7, "salary" : 180025 }, "sort" : [ 7, 180025 ] } ] } }
在上面的结果中,你可以看到,在具有相同经验级别的员工中,薪水最高的人在订单中被提前了(Alan 和 Winston 的经验级别相同,但与之前的搜索结果不同,这里 Alan 的排名被提升因为他的薪水更高)。
注意:如果我们改变排序数组中排序参数的顺序,即先保留 “salary” 参数,然后保留 “experience” 参数,那么搜索结果也会发生变化。 结果将首先根据薪水参数进行排序,然后将考虑经验参数,而不影响基于薪水的排序。
让我们将上述查询的排序顺序颠倒一下,即先保留 “salary”,然后是 “experience”,如下所示:
GET employees/_search?filter_path=**.hits { "_source": [ "name", "experience", "salary" ], "sort": [ { "salary": { "order": "desc" } }, { "experience": { "order": "desc" } } ] }
结果如下:
{ "hits" : { "hits" : [ { "_index" : "employees", "_type" : "_doc", "_id" : "4", "_score" : null, "_source" : { "name" : "Alan Thomas", "experience" : 12, "salary" : 300000 }, "sort" : [ 300000, 12 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "2", "_score" : null, "_source" : { "name" : "Othilia Cathel", "experience" : 11, "salary" : 193530 }, "sort" : [ 193530, 11 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "1", "_score" : null, "_source" : { "name" : "Huntlee Dargavel", "experience" : 7, "salary" : 180025 }, "sort" : [ 180025, 7 ] }, { "_index" : "employees", "_type" : "_doc", "_id" : "3", "_score" : null, "_source" : { "name" : "Winston Waren", "experience" : 12, "salary" : 50616 }, "sort" : [ 50616, 12 ] } ] } }
你可以看到经验值 12 的候选人低于经验值 7 的候选人,因为后者的薪水高于前者。
继续阅读 “Elasticsearch:Elasticsearch 查询示例 - 动手练习(二)”
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)