文章目录
搜索是ES中非常重要的功能,搜索的api是 _search
根据restful风格,搜索(查询)是幂等操作,http方法是GET请求。
基本语法:
GET /index/type/_search
共有六种搜索方式,都是基于以上语法,本文只写基本语法,具体的示例网上资料挺丰富的,不再重复咯。文末会贴参考链接
1、字符串(query string)搜索
我们像传递URL参数一样去传递查询语句:
语法:
GET /index/type/_search?q=field_name:queryCondition
GET /索引/类型/_search?q=字段名:字段值
注意 ?q 是语法中的一部分哦。指的是拼接参数。
适用于临时的在命令行使用一些工具,比如curl,快速的发出请求,来检索想要的信息;但是如果查询请求很复杂,是很难去构建的,在生产环境中,几乎很少使用query string search
思考:
多个条件怎么拼接该参数?
示例:
GET /megacorp/employee/_search?q=last_name:Smith
2、query DSL
DSL:Domain Specified Language,特定领域的语言
http request body:请求体,可以用json的格式来构建查询语法,比较方便,可以构建各种复杂的语法,比query string search肯定强大多了
(1)查询所有的商品
GET /ecommerce/product/_search
{
"query": { "match_all": {} }
}
(2)条件查询,排序
查询名称包含yagao的商品,同时按照价格降序排序
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"name" : "yagao"
}
},
"sort": [
{ "price": "desc" }
]
}
(3)分页查询商品
总共3条商品,假设每页就显示1条商品,现在显示第2页,所以就查出来第2个商品
GET /ecommerce/product/_search
{
"query": { "match_all": {} },
"from": 1,
"size": 1
}
(4)指定搜索结果字段
指定要查询出来商品的名称和价格就可以
GET /ecommerce/product/_search
{
"query": { "match_all": {} },
"_source": ["name", "price"]
}
query DSL 更加适合生产环境的使用,可以构建复杂的查询
3、query filter/ filter DSL
示例
搜索商品名称包含yagao,而且售价大于25元的商品
GET /ecommerce/product/_search
{
"query" : {
"bool" : {
"must" : {
"match" : {
"name" : "yagao"
}
},
"filter" : {
"range" : {
"price" : { "gt" : 25 }
}
}
}
}
}
这个例子,看上去就是queryDSL的复杂版,为啥叫query filter?
本人的理解:
其实就是requestbody中,的关键字不一样。
queryDSL,关键字比较简单,query、sort、from、size,_search
filterDSL,看上去就比较复杂了点,像本例中的filter、bool都是filter的关键字。
也有比较专业解释二者区别的:
query DSL 和query filter的区别
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
查询上下文 是在 使用query进行查询时的执行环境,比如使用search的时候。
一些query的场景:
与full text search的匹配度最高
包含run单词,如果包含这些单词:runs、running、jog、sprint,也被视为包含run单词
包含quick、brown、fox。这些词越接近,这份文档的相关性就越高
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用Must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
一些过滤的情况:
创建日期是否在2013-2014年间?
status字段是否为published?
lat_lon字段是否在某个坐标的10公里范围内?
关于二者的区别联系不多介绍,可以查看参考网址(以上文字也是摘抄自该文章)。
参考网址:https://www.cnblogs.com/bainianminguo/articles/10396956.html
4、full-text search(全文检索)
全文检索是关系型数据库比较难处理的,但ES可以轻松的解决,这得益于它的基本原理:为每一个字段都创建倒排索引,关于这部分理论内容,参考文章:Elasticsearch-入门到精通-1 学习路线及概念
本例中,假设有这样几条数据:
id | name | desc | price | producer | tags |
---|---|---|---|---|---|
1 | gaolujie yagao | gaoxiao meibai | 30 | gaolujie producer | meibai,fangzhu |
2 | jiajieshi yagao | youxiao fangzhu | 25 | jiajieshi producer | fangzhu |
3 | zhonghua yagao | caoben zhiwu | 40 | zhonghua producer | qingxin |
4 | special yagao | special meibai | 50 | special yagao producer | meibai |
有这样的一个查询,查询producer字段中,包含yagao producer的数据:
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"producer" : "yagao producer"
}
}
}
咦,怎么看上去跟第二部分的query DSL的查询很像,是的没错,不过,这里主要想表达的是ES的全文检索的原理。
数据添加如ES的时候,ES会为每一个字段建立倒排索引,producer字段也是一样,如下:
term | posting list |
---|---|
special | 4 |
yagao | 4 |
producer | 1,2,3,4 |
gaolujie | 1 |
zhognhua | 3 |
jiajieshi | 2 |
查询条件中的yagao producer,会被分词为yagao和 producer
那么,查倒排索引,yagao会匹配到4,producer会匹配到1234文档,因此文档4的匹配度最高,也就是相关度最高,我们看查询结果:
其中id为4的_score属性,值是最高的,也就是相关度最高。
不过还有一个小疑问啊:
为什么1/3的相关度为0.25811607,而2的相关度为0.1805489?
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 0.70293105,
"hits": [
{
"_index": "ecommerce",
"_type": "product",
"_id": "4",
"_score": 0.70293105,
"_source": {
"name": "special yagao",
"desc": "special meibai",
"price": 50,
"producer": "special yagao producer",
"tags": [
"meibai"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "1",
"_score": 0.25811607,
"_source": {
"name": "gaolujie yagao",
"desc": "gaoxiao meibai",
"price": 30,
"producer": "gaolujie producer",
"tags": [
"meibai",
"fangzhu"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "3",
"_score": 0.25811607,
"_source": {
"name": "zhonghua yagao",
"desc": "caoben zhiwu",
"price": 40,
"producer": "zhonghua producer",
"tags": [
"qingxin"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "2",
"_score": 0.1805489,
"_source": {
"name": "jiajieshi yagao",
"desc": "youxiao fangzhu",
"price": 25,
"producer": "jiajieshi producer",
"tags": [
"fangzhu"
]
}
}
]
}
}
5、phrase search(短语搜索)
跟全文检索相对应,相反,全文检索会将输入的搜索串拆解开来,去倒排索引里面去一一匹配,只要能匹配上任意一个拆解后的单词,就可以作为结果返回
phrase search,要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配,才能作为结果返回
以上文中的数据做例子,看一个例子,注意与全文检索的区别是match_phrase 关键字:
GET /ecommerce/product/_search
{
"query" : {
"match_phrase" : {
"producer" : "yagao producer"
}
}
}
查询结果为:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.70293105,
"hits": [
{
"_index": "ecommerce",
"_type": "product",
"_id": "4",
"_score": 0.70293105,
"_source": {
"name": "special yagao",
"desc": "special meibai",
"price": 50,
"producer": "special yagao producer",
"tags": [
"meibai"
]
}
}
]
}
}
6、highlight search(高亮搜索结果)
关键字:highlight
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"producer" : "producer"
}
},
"highlight": {
"fields" : {
"producer" : {}
}
}
}
一些示例,包括返回值的说明,网上有不少示例,本文就不做演示了:
参考网址:
https://www.cnblogs.com/bigben0123/articles/11075949.html