(五)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", "*"));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章