Elasticsearch 7.x 小白到高手

elasticsearch 7.0 新特性之Intervals

2019-04-14  本文已影响49人  郭彦超

intervals query 允许用户精确控制查询词在文档中出现的先后关系,实现了对terms顺序、terms之间的距离以及它们之间的包含关系的灵活控制

1、介绍

为了更加简单灵活的控制查询时字符串在文本中匹配的距离与先后顺序,官方在es7.0引入了intervals query,用户可单一或者组合多个规则集合在某一个特定的text field上进行操作。

例如,我们用“my favourite food”这样一个字符串在my_text field里进行intervals查询,查询规则是该字符串出现在"hot water"或者“cold porridge”字符串的前面,那么query语句可以这样来写:

POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "my favourite food",
                "max_gaps" : 0,
                "ordered" : true
              }
            },
            {
              "any_of" : {
                "intervals" : [
                  { "match" : { "query" : "hot water" } },
                  { "match" : { "query" : "cold porridge" } }
                ]
              }
            }
          ]
        },
        "boost" : 2.0,
        "_name" : "favourite_food"
      }
    }
  }
}

简要概述上面语句,像包含“my favourite food is cold porridge”这样字符串的文档就会被检索到,因为“my favourite food ”出现在“cold porridge”前面,满足intervals query语法规则;另一个只包含了“when it's cold my favourite food is porridge ”字符串的文档就不会被匹配到,因为“cold” 和“porridge”出现在了“my favourite food”两边,不符合我们配置的intervals query语法规则。

2、参数

参数 描述
query 用户查询的字符串
max_gaps 字符串中每个词在text field中出现的最大词间距,超过最大间距的将不会被检索到;默认值是-1,即不限制,设置为0的话,query中的字符串必须彼此相连不能拆分
ordered query中的字符串是否需要有序显示,默认值是false,即不考虑先后顺序
analyzer 对query参数中的字符串使用什么分词器,默认使用mapping时该field配置的 search analyzer
filter 可以为query搭配一个intervals filter,该filter不同于Boolean filter 有自己的语法结构
参数 描述
intervals 一个interval集合,集合里面的所有match需要同时在一个文档数据上同时满足才行
max_gaps 多个interval查询在一个文档中允许的最大间距,超过最大间距的将不会被检索到;默认值是-1,即不限制,设置为0的话,所有的interval query必须彼此相连不能拆分
ordered 配置 intervals 出现的先后顺序,默认值false
filter 可以为query搭配一个intervals filter,该filter不同于Boolean filter 有自己的语法结构
参数 描述
intervals 一个interval集合,集合里面的所有match不需要同时在一个文档数据上同时满足
filter 可以为query搭配一个intervals filter
POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "match" : {
          "query" : "hot porridge",
          "max_gaps" : 10,
          "filter" : {
            "not_containing" : {
              "match" : {
                "query" : "salty"
              }
            }
          }
        }
      }
    }
  }
}

参数说明:

参数 描述
containing interval query中terms之间需要包含filter中的terms
contained_by interval query中的字符串需要被包含在filter query的terms里
not_containing containing 对立面
not_contained_by contained_by 对立面包
not_overlapping query 与filter 词距不重叠
POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "match" : {
          "query" : "hot porridge",
          "filter" : {
            "script" : {
              "source" : "interval.start > 10 && interval.end < 20 && interval.gaps == 0"
            }
          }
        }
      }
    }
  }
}

3、Minimization

itervals query 会优化最小化间距,使得查询性能保持在一个线性可控的范围内;itervals query有时候会出现意想不到的查询结果,尤其是在使用了max_gaps来限制查询间距,例如查询包含salty 但必须出现在hot porridge词间:

POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "match" : {
          "query" : "salty",
          "filter" : {
            "contained_by" : {
              "match" : {
                "query" : "hot porridge"
              }
            }
          }
        }
      }
    }
  }
}

上面的查询不会匹配“hot porridge is salty porridge”,因为这两个term只是在文档中出现而没有覆盖salty。

还有另外一种情况,是在使用 any_of 时,如果包含了多个interval,且其中一个短语是另一个的前缀,那么较长的哪个interval将不会工作,例如查询“the”,后面需要紧跟“big”或“big dad”,最后紧跟“wolf”:

POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "all_of" : {
          "intervals" : [
            { "match" : { "query" : "the" } },
            { "any_of" : {
                "intervals" : [
                    { "match" : { "query" : "big" } },
                    { "match" : { "query" : "big bad" } }
                ] } },
            { "match" : { "query" : "wolf" } }
          ],
          "max_gaps" : 0,
          "ordered" : true
        }
      }
    }
  }
}

这个查询不会匹配到包含“the big bad wolf”内容的文档,在一个intervals组合规则里“big”是“big bad”的前缀,所以“big bad”被最小化了,如果想实现该效果,需要进行query重写,如:

POST _search
{
  "query": {
    "intervals" : {
      "my_text" : {
        "any_of" : {
          "intervals" : [
            { "match" : {
                "query" : "the big bad wolf",
                "ordered" : true,
                "max_gaps" : 0 } },
            { "match" : {
                "query" : "the big wolf",
                "ordered" : true,
                "max_gaps" : 0 } }
           ]
        }
      }
    }
  }
}
上一篇 下一篇

猜你喜欢

热点阅读