(五)elasticsearch之查询(Query DSL)
elasticsearch之查询(Query DSL)
一、字段类查询
字段类查询主要包含以下2类:
- 全文匹配:针对text 类型的字段进行全文检索,会对查询语句先进行分词处理,如match、match_phrase等query类型
- 单词匹配:不会对查询语句进行分词处理,直接去匹配字段的倒排索引,如term、terms、range等query 类型
补:match、match_phase、term、query_string的区别
1.term结构化字段查询,匹配一个值,且输入的值不会被分词器分词。
比如查询条件是:
{
"query":{
"term":{
"foo": "hello world"
}
}
}
那么只有在字段中存储了“hello world”的数据才会被返回,如果在存储时,使用了分词,原有的文本“I say hello world”会被分词进行存储,不会存在“hello world”这整个词,那么不会返回任何值。
但是如果使用“hello”作为查询条件,则只要数据中包含“hello”的数据都会被返回,分词对这个查询影响较大。
2.match_phase习语匹配,查询确切的phase,在对查询字段定义了分词器的情况下,会使用分词器对输入进行分词,然后返回满足下述两个条件的document:
1.match_phase中的所有term都出现在待查询字段之中
2.待查询字段之中的所有term都必须和match_phase具有相同的顺序
{ "foo":"I just said hello world" }
{ "foo":"Hello world" }
{ "foo":"World Hello" }
3.使用match_phase:
{
"query": {
"match_phrase": {
"foo": "Hello World"
}
}
}
会返回前两条文档。
注:slop 参数
通过 slop 参数可以控制单词间的间隔,如设置”slop”: “2”,则表示单词间可以隔2个单词。
3.match模糊匹配,先对输入进行分词,对分词后的结果进行查询,文档只要包含match查询条件的一部分就会被返回。
4.query_string语法查询,同match_phase的相同点在于,输入的查询条件会被分词,但是不同之处在与文档中的数据可以不用和query_string中的查询条件有相同的顺序。
5.match之 operator参数
通过 operator 参数可以 控制 单词间的匹配关系,可选项是 or 和 and。
因此,当你希望match 实现 分词 但词语必须都包含的情况时,可以修改此参数来达到目的,如下:
GET testindex/_search
{
"query": {
"match": {
"name": {
"query": "hello world",
"operator": "and"
}
}
}
}
6.match 之 minimum_should_match 参数
通过minimum_should_match 参数可以控制需要匹配的单词数。
例:
// 任意满足其中2个单词即可
GET testindex/_search
{
"query": {
"match": {
"name": {
"query": "i want to say hello",
"minimum_should_match": "2"
}
}
}
}
二、相关性算分
1、介绍
- 相关系算分是指文档与查询语句之间的相关度。
- 本质是一个排序问题,排序的依据是相关性算分。
2、相关概念
- Term Frequency(TF)词频,即单词在该文档中出现的次数。词频越高,相关度越大;
- Document Frequency(DF)文档频率,即单词出现的文档数;
- Inverse Document Frequency(IDF)逆向文档频率,与 DF 相反,简单理解是1/DF。即单词出现的文档数越少,相关度越大;
- Filed-length Norm 文档越短,相关性越大。
3、es 的主要相关性算分模型
- TF/IDF 模型
- BM25 模型,5.x之后的默认模型
4、explain 参数(请联想下explain在mysql的作用)
可以通过explain 参数来查看具体的计算方法,但需要主要以下几点:
- es 的算分是按照shard 进行的,即 shard 的分数计算是相互独立的,所以在使用 explain的时候注意分片数
- 可以通过设置索引的分片数为 1来避免这个问题
例:
GET testindex/_search
{
"explain": true,
"query": {
"match": {
"name": "kate"
}
}
}
// 设置shards分片数
PUT testindex
{
"settings": {
"index": {
"number_of_shards": "1"
}
}
}
三、复杂查询之 constant_score 查询
- 该查询将其内部的查询结果文档得分都设定为1 或者boost 的值;
- 常用于 结合 bool 查询实现自定义得分。
语法如下:
GET testindex/_search
{
"query": {
"constant_score": {
"filter": { // 只能有一个
"match": {
"name": "kate"
}
}
}
}
}
四、复杂查询之 bool 查询
bool 查询可由一个或多个布尔子句组成,主要包含如下4类:
filter | 只过滤符合条件的文档,不计算相关性得分 |
---|---|
must | 文档必须符合 must中的所有条件,会影响相关性得分 |
must_not | 文档必须不符合 must_not 中的所有条件,不计算相关性得分 |
should | 文档可以符合 should 中的所有条件,会影响相关性得分 |
1、filter
- filter 查询只过滤符合条件的文档,不计算相关性得分
- es针对 filter 会有智能缓存,因此其执行效率很高
- 做简单匹配查询且不考虑算分时,推荐使用 filter 替代 query 等
语法如下:
GET testindex/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"name": "kate"
}
}
]
}
}
}
2、should
should 使用分为2种情况:
(1)bool 查询只包含 should,不包含must查询
此时,文档满足一个条件即可。
可通过minimum_should_match 来控制满足条件的个数。
(2)bool 查询同时包含 should 和 must查询
此时,文档必须满足must 的条件,should可以不满足,但是如果满足了should 条件,会增加相关性得分。
五、其他 api
1、_count
统计文档数目
2、_source
过滤返回结果中 _source 中的字段,主要有以下几种用法
用法一:
GET testindex/_search?_source=name
用法二:
GET testindex/_search
{
"_source": false
}
用法三:
GET testindex/_search
{
"_source": ["name","age"]
}
用法四:
GET testindex/_search
{
"_source": {
"includes": "name",
"excludes": "age"
}
}
六、常见的查询问题
1、查询字段是否存在
GET testindex/_search
{
"query": {
"exists": { // 关键字
"field": "price" // price 字段
}
}
}
2、查询空字符串的字段(字段存在,内容是空字符串)
// 利用 wildcardQuery 和 mustNot搭配,可以查到空字符串内容的值
BoolQueryBuilder mustNot = QueryBuilders.boolQuery()
.must(QueryBuilders.existsQuery("group_name"))
.mustNot(QueryBuilders.wildcardQuery("group_name", "*"));
还没有评论,来说两句吧...