四.全文检索ElasticSearch经典入门
前言
上一章节我们学习的是ElasticSearch的基础操作,在实际的开发中可不只是CURD那么简单,往往伴随着复杂的搜索场景,本篇文章我们将学习如何在ElasticSearch中进行复杂的全文检索。
简单查询
查询所有数据可以使用 GET _search ,查询某个索引库中的所有数据可以使用 GET index/_search
GET orders/_search 1
携带分页条件
GET orders/_search?size=2&from=2 1
size是每页条数; from是跳过的条数,和mysql的limit是一样的含义,效果如下:
携带查询参数可以通过 q= ,比如查询count为1的
GET orders/_search?q=count:1&size=10&from=0 1
需要带排序条件通过 sort=列:desc 指定 desc是倒排,正排是asc ,比如按在价格倒排
GET orders/_search?q=count:1&sort=amount:desc&size=10&from=0 1
下面是URL中可以携带的参数
批量查询
批量查询很重要,对相比单个查询来说,批量查询性能更高。第一种批量查询可以同时查询多个索引库中的文档
GET _mget { "docs" : [ { "_index" : "orders", "_type" : "_doc", "_id" : 1 }, { "_index" : "goods", "_type" : "_doc", "_id" : 1, "_source": ["id","title","amount"] } ] }
12345678910111213141516这里的_source 指的是查询的列 ,查询效果如下
第二种批量获取方式是获取同一个索引库中的多个文档
GET orders/_doc/_mget {"ids" : [ 1, 2 ] } 1234
查询效果如下
版本号控制
ES利用_version 版本号来解决线程并发导致数据丢失问题。需要修改数据时需要指定想要修改文档的version号,如果该版本不是当前版本号,请求将会失败
ElasticSearch中有内部版本号和外部版本号之分。使用内部版本号是要求指定的version字段和当前的version号相同。但在使用外部版本号时要求当前version号小于指定的版本号。如果请求成功,外部版本号作为文档新的version号进行存储。详细参见:连接
外部版本号:
PUT /orders/_doc/2?version=5&version_type=external 1
内部版本号:
PUT /orders/_doc/1?version=1 1
新版本使用_seq_no和_primary_term来代替version处理并发问题,比如有如下数据
{ "_index" : "orders", "_type" : "_doc", "_id" : "1", "_version" : 16, "_seq_no" : 17, "_primary_term" : 3, "found" : true, "_source" : { "id" : 1, "title" : "买了1个罗技鼠标", "amount" : 200.0, "count" : 1, "status" : 1 } }
12345678910111213141516修改的时候使用乐观锁控制 ,如果版本号错误,会出现 “version_conflict_engine_exception”错误
PUT orders/_doc/1?if_primary_term=3&if_seq_no=17 { "id":1, "title":"买了1个罗技鼠标", "amount":200.00, "count": 1, "status":1 } 12345678
DSL查询与DSL过滤
对于简单查询,使用查询字符串比较好,但是对于复杂查询,由于条件多,逻辑嵌套复杂,查询字符串不易组织与表达,且容易出错,因此推荐复杂查询通过DSL使用JSON内容格式的请求体代替。
DSL查询是由ES提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。DSL主要分为查询DSL(query DSL)和过滤DSL(filter DSL)。
一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score ,并且 按照相关性对匹配到的文档进行,查询语句同时匹配文档,计算相关性,所以更耗时,且不缓存。
一条过滤语句会询问每个文档的字段值是否包含着特定值,它不会去计算任何分值也不关心排序,因此效率会高一点,过滤结果可以缓存并应用到后续请求,过滤语句可有效地配合查询语句完成文档过滤。另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
看到这里可能还是不太理解DSL查询与DSL过滤的具体区别,我们来举个例子
我们可以把京东的列表搜索功能分为两部分,第一部分是“关键词”搜索 ; 第二部分是下方的各种条件。那么使用DSL应该怎么做呢?
我们可以把下方的所有条件直接使用DSL过滤来做,因为DSL过滤更像是精品匹配,有或者没有且性能好。对于关键字搜索部分我们通常是放入到 DSL查询部分来做,因为我们通常可以根据关键字进行相关性排序。
一个常用的相对完整的DSL查询
案例:查询索引库orders 中 title包含鼠标的商品,查询第 1 页,每页10条,按照amount 倒排序
GET /orders/_doc/_search {"query": {"match": { "title":"鼠标"}},"from": 0,"size": 10,"_source": ["id", "title", "amount","count"],"sort": [{"amount": "desc"}] } 123456789101112 match : ES的一种查询方式,叫标准匹配,会把搜索的关键字分词后再进行匹配,效果如同: where title = 鼠 or title = 标
DSL查询和DSL综合案例
数据准备,写入两条订单数据
PUT orders/_doc/1 { "id":1, "title":"买了1个罗技鼠标", "amount":200.00, "count": 1, "status":1 } PUT orders/_doc/2 { "id":2, "title":"买了2个华为鼠标", "amount":100.00, "count": 2, "status":1 }
12345678910111213141516案例:查询索引库orders 中 title包含鼠标的商品,amount在 100 到 200 之间 , 状态status为 1的,查询第 2 页,每页10条,按照amount 倒排序
GET /orders/_doc/_search {"query": {"bool": {"must": [{"match": {"title": "鼠标"}}],"filter": [{ "range":{ "amount":{ "gte":100, "lte":200 } }},{"term": {"status": 1}}]}},"from": 10,"size": 10,"sort": [{"amount": "desc"}] }
123456789101112131415161718192021222324252627282930bool :代表的是组合查询,把多种查询方式组合到一起,bool下面包含了must和filter;must和filter里面都可以包含多个查询条件
must : bool组合了must和filter , must中的语句是DSL查询,filter中的语句是DSL过滤。must代表其中的条件是必须满足,还可以把must指定为 should 和 must_not;这个位置的语句会进行相关性计算,且按照分数排序,一般会把关键字查询放到这里。
should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
must_not : 文档必须不匹配条件
filter : 过滤,里面的查询语句不会处理相关性等,但是会对查询的结果进行缓存,性能好
range : 指的是范围 ;get是大于等于 ;let是小于等于
term :词元匹配,可以理解为精准匹配,可以用于字符串,数字等类型
from : 第2页应该是 (2 - 1 )* 每页条数10
DSL中的查询条件
在上面综合案例中我们用到了4种查询方式:bool ;match ;range ;term ,在ES中还有很多的查询方式来满足我们各种需求
全匹配(match_all):普通搜索(匹配所有文档)GET _search { "query": { "bool": { "must": [ { "match_all": {} } ], "filter": { ... } } } } 123456789101112131415 标准查询(match和multi_match)
标准查询,可以理解为,分词查询有点像模糊匹配(like),但又不像,它会对查询的内容进行分词后,得到多个单词,分别带着多个单词去检索ES库,只要有一个单词能查出结果,整个查询就有结果。不管你需要全文本查询还是精确查询基本上都要用到它。
如下面的搜索会对Steven King分词,并找到包含Steven或King的文档,然后给出排序分值。
{"query": {"match": {"fullName": "Steven King"}} } 1234567
注意:上面效果如同 where fullName = "Steven" or fullName = "King" ; multi_match 查询允许你做 match查询的基础上同时搜索多个字段:
{"query": {"multi_match": {"query": "Steven King","fields": ["fullName", "title"]}} } 123456789101112
上面效果如同:where fileName = Steven or fileName = title or King = fullName or King = title
单词搜索与过滤(Term和Terms)
单词/词元查询 , 可以理解为等值查询,字符串,数字等都可以使用它,把查询的内容看成一个整体去检索ES库
{ "query": { "bool": { "must": { "match_all": { } }, "filter": { "term": { "username": "Steven King" } } } } }
12345678910111213141516上面效果如同:where username = "Steven King"
提示:上面的“Steven King”会被当成一个词去username中匹配,它跟match不同的地方在于match会把“Steven King”分成“steven”和“king”分别去username中查询。
Terms支持多个字段查询
{ "query": { "terms": { "username": [ "jvm", "hadoop", "lucene" ], "minimum_match": 1 } } } 123456789101112
提示:minimum_match:至少匹配个数,默认为1 ,也就是说username中至少出现三个单词中的一个。
组合条件搜索与过滤(Bool)
组合搜索bool可以组合多个查询条件为一个查询对象,查询条件包括must、should和must_not。
例如:查询爱好有美女,同时也有喜欢游戏或运动,且出生于1990-06-30及之后的人。
{ "query": { "bool": { "must": [ { "term": { "hobby": "美女" } } ], "should": [ { "term": { "hobby": "游戏" } }, { "term": { "hobby": "运动" } } ], "must_not": [ { "range": { "birth_date": { "lt": "1990-06-30" } } } ], "filter": [ ... ] } } }
12345678910111213141516171819202122232425262728293031323334353637上面案例如同:Hobby=美女 and (hobby=游戏 or hobby=运动) and birth_date >= 1990-06-30
提示: 如果 bool 查询下没有must子句,那至少应该有一个should子句。但是 如果有 must子句,那么没有 should子句也可以进行查询。
范围查询与过滤(range)
range过滤允许我们按照指定范围查找一批数据
{ "query": { "range": { "age": { "gte": 20, "lt": 30 } } } } 12345678910
上例中查询年龄大于等于20并且小于30。gt:> gte:>= lt:< lte:<=
存在和缺失过滤器(exists和missing)
{ "query": { "bool": { "must": [ { "match_all": { } } ], "filter": { "exists": { "field": "gps" } } } } }
123456789101112131415161718提示:exists和missing只能用于过滤结果。
前匹配搜索与过滤(prefix)
和term查询相似,前匹配搜索不是精确匹配,而是类似于SQL中的like ‘key%’
{ "query": { "prefix": { "fullName": "王" } } } 1234567
提示:上例即查询姓王的所有人。
通配符搜索(wildcard)
使用*代表0~N个,使用?代表1个。
{ "query": { "wildcard": { "fullName": "王*锤" } } } 1234567
文章到这里就结束了,喜欢的话请给个好评,你的鼓励是我最大的动力,评论过百,我就是秃头也出下章。
相关知识
中文期刊全文数据库检索方法与技巧
希腊罗马史数据库检索入门—Clauss
检索字段符课件
计算与检索方法
信息检索ISI
检索课堂第二期:中文文献检索不到?几招助你熟能生巧
全文搜索 (SQL Server)
经典植物分类学方法详解.pdf
十大日本枫树入门品种推荐
如果分别以检索词 a、b、c在某数据库的关键词字段进行检索都能得到相应的检索结果
网址: 四.全文检索ElasticSearch经典入门 https://www.huajiangbk.com/newsview105138.html
上一篇: JavaScript DOM 编 |
下一篇: SEO艺术阅读笔记 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039