elasticsearch篇之SearchAPI
Search APISearch API功能Search API 实现了对es中存储的数据进行查询分析,endpoint为 _search第一种是对es中所有的数据进行查询第二种是对指定的index查询第三种是对多个index同时查询第四种是对指定通配符的index进行查询查询的两种形式URI Search操作简便,方便通过命令进行测...
Search API
Search API功能
Search API 实现了对es中存储的数据进行查询分析,endpoint为 _search
第一种是对es中所有的数据进行查询
第二种是对指定的index查询
第三种是对多个index同时查询
第四种是对指定通配符的index进行查询
查询的两种形式
URI Search
操作简便,方便通过命令进行测试,仅包含部分查询语法
这种方式适合做命令行的测试
Request Body Search
es提供的完备查询语法 Query DSL
URI Search
URI Search就是通过拼接关键字来进行搜索的。
参数
- q:指定查询语句,语法遵循 Query String Syntax
- df:q中不指定字段时默认的查询字段,如果不指定,es会查询所有字段
- sort:排序
- timeout:指定超时时间,默认不超时
- from,size:用于分页
Query String Syntax
查询方式
实例
首先创建索引:
PUT test_search_index
{
"settings": {
"index": {
"number_of_shards": "1"
}
}
}
创建测试文档:
POST test_search_index/doc/_bulk
{
"index": {
"_id": "1"
}
}
{
"username": "alfred way",
"job": "java enginner",
"agr": 18,
"birth": "1999-1-1",
"isMarried": false
}
{
"index": {
"_id": "2"
}
}
{
"username": "alfred",
"job": "java senior and java test",
"age": 29,
"birth": "1989-1-1",
"isMarried": true
}
{
"index": {
"_id": "3"
}
}
{
"username": "lee",
"job": "java senior and ruby test",
"age": 10,
"birth": "2010-1-1",
"isMarried": false
}
{
"index": {
"_id": "4"
}
}
{
"username": "alfred jr way",
"job": "ruby test",
"age": 1,
"birth": "2019-1-1",
"isMarried": false
}
一个泛查询:
// 在所有字段中,只要包含alfred的字段的文档就返回
GET test_search_index/_search?q=alfred
查看查询语句的执行过程
GET test_search_index/_search?q=alfred
{
"profile": true
}
一般用来做查询语句调优
指定字段的查询
// 只返回username字段包含alfred的文档
GET test_search_index/_search?q=username:alfred
如果指定的关键字为下面的情况:
GET test_search_index/_search?q=username:alfred way
它表示返回username包含alfred或者所有字段匹配到way的文档,所以返回的结果和上面一样,通过查看具体查询过程可以看出来
词语查询
// 需要在查询的词语上添加双引号
GET test_search_index/_search?q=username:"alfred way"
组查询
// 通过添加括号表示匹配username为alfred或way字段的文档
GET test_search_index/_search?q=username:(alfred way)
这个和之前指定字段查询的区别是,在查询中只会匹配username为alfred或username为way的字段,而不会做泛查询。
布尔查询
GET test_search_index/_search?q=username:alfred AND way
但是这样写表示返回匹配到username为alfred,泛查询全部字段匹配到way的文档。
想要返回只匹配username字段匹配到alfred和way的文档就加一个括号:
GET test_search_index/_search?q=username:(alfred AND way)
这里由于先前文档录入的时候没能体现这点的区别所以两种查询语句的结果相同,但是在实际中很大可能两种语句的查询结果是不同的。
// 返回username中不要有way但是可以由alfred的文档
GET test_search_index/_search?q=username:(alfred NOT way)
然后看一下 + 的情况:
// 返回username中可以由alfred但必须有way的文档
GET test_search_index/_search?q=username:(alfred +way)
可以看到最后一个文档并不符合我们的预期,因为在html中,加号被解析为空格,所以需要使用%2B代替加号
// 返回username中可以由alfred但必须有way的文档
GET test_search_index/_search?q=username:(alfred %2Bway)
范围查询
// 查询username包含alfred或age大于20的文档
GET test_search_index/_search?q=username:alfred age:> 20
// 查询username包含alfred且age大于18的文档
GET test_search_index/_search?q=username:alfred AND age:>18
// 查询birth在1980到2000之间的文档
GET test_search_index/_search?q=birth:(>1980 AND <2000)
通配符查询
// 查询username以 alf来头的所有的文档
GET test_search_index/_search?q=username:alf*
正则表达式匹配
// 匹配 [a]?l.* 这个正则匹配到的所有文档
GET test_search_index/_search?q=username:/[a]?l.*/
正则表达式匹配也比较吃内存,所以在文档数较多的时候应减少使用正则匹配
模糊匹配和相似度查询
// 查询与alfed有N个单位偏差的文档,波浪线后边的数字表示允许偏差的个数
GET test_search_index/_search?q=username:alfed~1
GET test_search_index/_search?q=username:alfed
GET test_search_index/_search?q=username:alfd~2
这样可以做到当用户误输入的时候也能查询到正确信息
词语查询也可以做到相似度查询:
GET test_search_index/_search?q=job:"java test"~1
这个表示允许在java test中间增加1个词语
如果是增加三个单词:
GET test_search_index/_search?q=job:"java test"~3
Request Body Search
Request Body Search 就是将 http request body 发送到es,主要参数如下:
- query:符合 Query DSL语法
- from,size
- timeout
- sort
…
Query DSL
这是一个基于 JSON 定义的查询语言,主要包含两种类型:
字段查询:如 term、match、range等,只针对某一字段进行查询
复合查询:如bool查询等,包含一个或多个字段类查询或复合查询语句
Query DSL- 字段类查询
字段类查询主要包含下面的两类:
match query
这个语句就表示返回包含alfred或way的文档。
match query的流程
match query参数
在前面的查询中待查询语句满足其中的一个即可,es提供了一个参数用来表示查询语句匹配关系:
这个例子中就表示必须同时包含alfred和way
还有一个参数用于控制需要匹配的单词数:
这个例子就表示:至少包含查询语句中的2个term才能匹配。
相关性算分
在match query流程中,汇总的分的过程是es根据内部的相关性算分算法(TF/IDF、BM25等)进行计算的。在es5.x版本后默认使用BM25算法进行相关性算分。
相关性算分是指文档与查询语句之间的相关度(relevance)。其本质是一个排序问题,就是当通过倒排索引获取到匹配的文档列表后,如何将最符合用户需求的文档排在前列。
相关性算分具有如下的重要概念:
TF/IDF算法是Lucene的经典算法,计算公式如下:
BM25算法中BM指的是BEST MATCH,25指的是迭代了25次才计算方法,是针对TF/IDF的一种优化,计算公式如下:
match phrase query
对字段有检索,有顺序要求,API如下:
这个例子是:匹配java和engineer关键字的文档,且java要在engineer前面。
match phrase query参数
通过slop参数控制单词间的间隔:
这样额话,就表示允许匹配的文档可以与 java engineer有一个距离的差异。这样,java senior engineer这样的字段就可以返回了。
query string query
类似于 URI search中的q参数查询:
这个例子就表示返回返回username字段中包含alfred和way的文档
这个表示查询username 和 job字段,条件是包含alfred或同时包含java和ruby
simple query string query
类似于query string,但是会忽略掉错误的查询语法,并且仅支持部分的查询语法。不能使用 AND,OR,NOT等关键词,使用 +代替AND, | 代替OR,- 代替 NOT。
Term query
将查询语句作为一个整体进行查询,不进行分词:
Terms query
一次传入多个单词进行查询:
range query
范围查询主要针对日期和数值类型:
Date Math是针对日期的一种更友好的计算格式:
主要的时间单位有:y(year)、M(months)、w(week)、d(days)、h(hours)、m(minutes)、s(seconds)
复合查询
复合查询是指包含字段类查询或复合查询的类型,主要有以下几种:
- constant_score query
- bool query
- dis_max query
- function_score query
- boosting query
constant_score query将其内部的查询结果文档得分都设定为1或者boost的值,多用于结合bool查询实现自定义得分:
在返回的结果中,_score的值全部为1
bool query由一个或多个bool子句组成,主要包含以下4个:
filter查询只返回符合条件的文档而不关心相关性,不进行相关性算分。es对filter有智能缓存,所以其执行效率很高。所以在执行简单查询而不考虑相关性的时候推荐使用filter代替query等。
执行结果中的_score的值为0,表示没有进行相关性算分
must指定了必须符合的条件:
must_not是指排除must_not中符合条件的文档:
should的使用有两种情况:
- bool查询中只包含should,不包含must查询
- bool查询中同时包含should和must查询
query context 和filter context的区别
count api
这个api是用于返回符合条件的文档数,endpoint为_count
source filtering
过滤返回结果中_source的字段,节省网络开销:
更多推荐
所有评论(0)