索引:
===========这里才是开始============
Search API实现了对es中存储的数据进行查询分析,endpoint为_search,如下图所示:
分别对应的功能:
- 查询所有es中的数据
- 对相应index进行查询
- 对多个index做查询
- 用通配符进行查询
查询主要由两种形式
第一种形式:URI Search
- 操作简单,方便通过命令行进行测试
- 仅包含部分查询语法
通过url query参数来实现搜索,常见参数有:
- q 指定查询的语句,语法为Query String Syntax
- df q 中不指定字段时默认查询的字段,如果不指定,es会查询所有的字段
- sort 排序
- timeout 指定超时的时间,默认不超时
- from,size用于分页
term与phrase
- alfred way 等效于alfred OR way
- “alfred way”词语查询,要求先后顺序
泛查询:
- alfred等效于在所有字段去匹配该term
指定字段:
- name: alfred
Group分组设定,使用括号指定匹配规则
- (quick OR brown) AND fox 括号内的优先级高
- status:(active OR pending) title:(full text search) 括号将关键词作为一个整体,不加括号的话就成了status是active或者所有包含pending的字段
EXAMPLE:插入字段并查询包含afred的字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# data DELETE test_search_index PUT test_search_index { "settings": { "index":{ "number_of_shards": "1" } } } POST test_search_index/doc/_bulk {"index":{"_id":"1"}} {"username":"alfred way","job":"java engineer","age":18,"birth":"1990-01-02","isMarried":false} {"index":{"_id":"2"}} {"username":"alfred","job":"java senior engineer and java specialist","age":28,"birth":"1980-05-07","isMarried":true} {"index":{"_id":"3"}} {"username":"lee","job":"java and ruby engineer","age":22,"birth":"1985-08-07","isMarried":false} {"index":{"_id":"4"}} {"username":"alfred junior way","job":"ruby engineer","age":23,"birth":"1989-08-07","isMarried":false} GET test_search_index # search api GET test_search_index/_search?q=alfred GET test_search_index/_search?q=alfred { "profile":true } GET test_search_index/_search?q=username:alfred GET test_search_index/_search?q=username:alfred way { "profile":true } GET test_search_index/_search?q=username:"alfred way" { "profile":true } GET test_search_index/_search?q=username:(alfred way) { "profile":true } |
可以通过profile看到实际执行的query语句:
布尔操作符:
AND(&&) OR(||) NOT(!)
- name:(tom NOT lee) 查询包含同名但不包含lee的字段
- 注意大写,小写的话会认为是一个term
+ – 分别对应must和must not
- name:(tom + lee – afred) 返回name一定包含lee一定不包含afred但可以包含alfred
- name:((lee&&!afred)||(tom&&lee&&!alfred)) 同上的功能,但写起来更复杂
- +在ur会被解析成空格,要使用encode之后的结果才可以使用,为%2B
范围查询
支持数值和日期
通配符查询(效率很低不建议使用)
正则匹配查询(查询效率也低)
1 |
GET test_search_index/_search?q=username:/[a]?l.*/ |
模糊匹配及近似度匹配(用于帮助用户修成查询语句,对用户输入词进行纠错)
1 2 3 4 5 |
GET test_search_index/_search?q=username:alfed~1 GET test_search_index/_search?q=username:alfd~2 GET test_search_index/_search?q=job:"java engineer" GET test_search_index/_search?q=job:"java engineer"~1 GET test_search_index/_search?q=job:"java engineer"~2 |
第二种查询方式 Request Body Search(最普遍使用)
- es提供的完备查询语法Query DSL
Query DSL是一种基于JSON定义的查询语言,主要包含如下两种类型:
第一种类型,字段查询,如term,match,range等,只针对某一个字段进行查询
字段内查询主要包括以下两类
第一种查询方法 全文匹配:针对text类型的字段进行全文检索,会对查询语句先进行分词处理,如match、match_phrase等query类型
Match Query(最常用)
对字段做全文检索,最基本和常用的查询类型,API示例如下:
查询的是username中包含alfred或者way的返回结果:
执行流程:
可以通过operator参数控制单词间的匹配关系,可选项为or和and,默认是or,如果想查询同时包含afred和way的结果那么可以这样:
可以通过minimum_should_match 参数控制需要匹配的单词数,也就是说比如查询java ruby engineer三个词,必须有两个词匹配的结果才会返回:
相关性算分
在match query的流程图中,有一项汇总得分,这就是相关性算分
相关性算分是指文档与查询语句间的相关度,英文为relevance
- 通过倒排索引可以获取与查询语句相匹配的文档列表,那么如何将最符合用户查询需求的文档放在前列呢
- 本质是一个排序问题,排序的依据是相关性算分
相关性算分几个重要的概念:
- Term Frequency(TF):词频,即单词在该文档中出现的次数,词频越高,相关度越高
- Document Frequency(DF):文档频率,即单词出现的文档数
- Inverse Document Frequency(IDF):逆向文档频率,与文档频率相反,简单可理解为1/DF。即单词出现的文档数越少,相关度越高。
- Field-length Norm:文档越短,相关性越高
ES目前主要由两个相关性算分模型:
1.TF/IDF模型
可以通过explain参数来查看具体的计算方法,但是要注意:
- es的算分是按照shard进行的,及shard的分数计算是相互独立的,所以在使用explain的时候要注意分片数。
- 可以通过设置索引的分片数为1来避免这个问题
2.BM25模型 (默认)
Match Phrase Query:
对字段做检索,有顺序要求:
可以使用slop参数控制单词间的间隔
Query-String-Query
类似于URI Search中的q参数查询
Simple Query String
- 类似Query String,但是会忽略错误的查询语法,并且仅支持部分查询语法
- 其常用的逻辑符号如下,不能使用AND OR NOT 等关键词:
- + 代指 AND
- | 代指 OR
- – 代指 NOT
第二种查询方法 单词匹配 (不会做分词处理)
Term 和terms query
将查询语句作为整个单词进行查询,即不对查询语句做分词处理,如下所示:
一次可以传入多个单词进行查询
Range Query
范围查询主要针对数值和日期类型:
Range Query – Date Math
针对日期提供一种更友好的计算方式,格式如下:
第二种类型 复合查询
复合查询是指包含字段查询或复合查询的类型,主要包括以下两类(还有)
- constant_score query
该查询将其内部的查询结果文档得分都设定为1 或者boost的值
多用于结合bool查询实现自定义得分:
- bool query
布尔查询由一个或多个布尔子句组成,主要包含如下4个
API:
Filter查询只过滤复合条件的文档,不会进行相关性算分。
- es针对filter会有智能缓存,因此其执行效率很高
- 做简单匹配查询不考虑算分时,推荐使用filter替代query等
MUST 查询例子
MUST NOT排除所有MUST NOT里面的文档,一定不包含:
Should使用分为两种情况
1.第一种情况,只包含should,文档必须满足至少一个条件minimum_should_match可以控制满足条件的个数或者百分比
2.同时包含should和must时,文档不满足should中的条件,但是如果满足条件会增加相关性得分:
Fileter context 与 Filter Context的区别:
COUNT API
查询文档数
Source Filtering
过滤返回结果的数据集中的一些字段。