{
"id": "1",
"title": "努力改善农业生态环境"
}
当我们需要在title字段中查询“农业生态”字段时,将查询不到任何记录
{
"query": {
"match_phrase": {
"title": {
"query": "农业生态"
}
}
}
}
为什么title字段中包含有这个子字符串我们却查询不到呢,首先将title中的字段进行分词,看看结果:
{
"tokens":[
{
"token":"努力",
"start_offset":0,
"end_offset":2,
"type":"ad",
"position":0
},
{
"token":"改善",
"start_offset":2,
"end_offset":4,
"type":"n",
"position":1
},
{
"token":"农业",
"start_offset":4,
"end_offset":6,
"type":"n",
"position":2
},
{
"token":"生态环境",
"start_offset":6,
"end_offset":10,
"type":"nz",
"position":3
},
{
"token":"生态",
"start_offset":6,
"end_offset":8,
"type":"n",
"position":4
},
{
"token":"环境",
"start_offset":8,
"end_offset":10,
"type":"n",
"position":5
}
]
}
在上面的分词中,“农业生态环境”为分成了:农业、生态环境、生态、环境 这几个词
注意每个词条position的值,在农业和生态之间有一个生态环境,使得农业和生态的position位置相差了一位
下面我们在看一下我们需要查询的字符串的分词情况:
{
"tokens":[
{
"token":"农业",
"start_offset":0,
"end_offset":2,
"type":"n",
"position":0
},
{
"token":"生态",
"start_offset":2,
"end_offset":4,
"type":"n",
"position":1
}
]
}
可以看见我们需要查询的短语被分成了两个词条,并且他们的position位置是相邻的。我们再来看一下官方对match_phrase语法的解释:
Like the match query, the match_phrase query first analyzes the query string to produce a list of terms. It then searches for all the terms, but keeps only documents that contain all of the search terms, in the same positions relative to each other.
大致意思是说:使用match_phrase查询时,先对需要查询的字符串进行分词,然后返回包含所有词条的文档。最后一句in the same positions relative to each other.意思就是说用match_phrase查找时, 查找分词器分出的词的位置和要建索引时分出的词的位置一样。
在看我们上面的例子:
存储的原文:农业生态环境
分词及position:农业 0 生态环境 1 生态 2 环境 3
{
"analyzer": "hanlp-index",
"text": "农业生态生态"
}
{
"tokens":[
{
"token":"农业",
"start_offset":0,
"end_offset":2,
"type":"n",
"position":0
},
{
"token":"生态环境",
"start_offset":2,
"end_offset":6,
"type":"nz",
"position":1
},
{
"token":"生态",
"start_offset":2,
"end_offset":4,
"type":"n",
"position":2
},
{
"token":"环境",
"start_offset":4,
"end_offset":6,
"type":"n",
"position":3
}
]
}
查询的字符串:
需要查询的字符串:农业生态
分词及position:农业 0 生态 1
{
"analyzer": "hanlp-index",
"text": "农业生态"
}
{
"tokens":[
{
"token":"农业",
"start_offset":0,
"end_offset":2,
"type":"n",
"position":0
},
{
"token":"生态",
"start_offset":2,
"end_offset":4,
"type":"n",
"position":1
}
]
}
从上面的例子可以看出,数据index时,农业生态的position位置分别为 0和2
而我们检索的时候农业生态的position位置分别为0和1
在match_phrase看来,这种是不匹配的,所以使用农业生态检索不出农业生态环境的记录。这就是官方对match_phrase语法最后一句的解释。
对需要查询字符串的字段使用默认分词。默认分词将会把每一个汉字分开,一个汉字作为一个词条
设置mapping的时候对字段使用默认分词(直接指定字段类型为text即可)
{
"title":{
"type":"text"
}
}
针对于汉字就是一个一个分,这种肯定是可以查全的。但一个一个字分的话,每个字对应的文档集合非常多,如果数据量达到了百亿,在求交集,计算距离时,效果非常差。
在使用match_phrase查询的时候指定slop参数
{
"query": {
"match_phrase": {
"title": {
"query": "农业生态",
"slop": 1
}
}
}
}
slop参数的值即表示允许词条position的差值。使用该方法虽然可以解决上面的问题,但是在查询的返回列表中将会返回一些不满足情况的数据,如下面的查询:
{
"query": {
"match_phrase": {
"title": {
"query": "改善环境",
"slop": 1
}
}
}
}
返回的数据中将包含:
“改善投资环境“ 的数据。因为在改善投资环境中,改善和投资的position也是相差1的。
使用match_phrase_prefix 语法查询。该语法在短语查询的基础上还加上了词条的前缀匹配。
{
"query": {
"match_phrase_prefix": {
"title": {
"query": "农业生态"
}
}
}
}
基本可以达到精确查询的需求