elk笔记13--Queries-full text queries

1 full text 查询简介

全文查询允许用户查询被解析后的text(分词)字段,例如邮件的正文。全文检索时候,查询字符串会按照写入时候的解析方式来解析为单个的数据项。

全文查询包括如下9类:

  1. intervals query
    intervals 查询允许对匹配项有一个细粒度的顺序和距离控制。
  2. match query
    match 查询是执行全文检索的标准查询,包括 fuzzy matching 和 phrase or proximity. queries.
  3. match_bool_prefix query
    match_bool_prefix 查询创建一个bool 查询,该bool查询将每个term做为一个term查询,最后一个term做为一个prefix 查询。
  4. match_phrase query
    Like the match query but used for matching exact phrases or word proximity matches.
    和match 查询一样,但是该查询用于匹配精确的短语或者单词距离匹配。
  5. match_phrase_prefix query
    和match_phrase 一样, 但是其对最后一个单词执行统配查询|前缀查询.
  6. multi_match query
    该查询是一个多字段版本的match查询,即1个query字符串对应多个field字段.
  7. common terms query
    该查询是一种更加专业的查询方式,它给不寻常的单词(停用词)更多偏好.
  8. query_string query
    该查询支持简洁的 Lucene 查询字符串语法, 允许用户在单个查询字符串中指定 AND|OR|NOT 等条件 和 multi-field 搜索. 该查询适用于熟练的用户,kibana discover 就是用这种查询实现的.
  9. simple_query_string query
    该查询是一个更加简单、健壮版本 query_string 语法的插叙,适用于直接暴露给用户。

2 full text 查询类型

2.1 intervals query

该查询基于匹配项的顺序和距离返回文档。
intervals 使用多个匹配规则,并将这些规则应用到特定字段的数据项中。
这些规则由一系列定义组成。这些定义产生了跨越数据项的最小intervals序列。这些intervals 可以进一步被父资源组合、过滤。

该查询顶层参数为 field,子参数包括 match、any_of、all_of、filter 四种规则,每种规则又可以包含很多其它参数,并且可以嵌套使用。

以下案例为intervals查询,其规则为all_of, 它能够查询到my_text字段中包含 "my favorite food immediately ",且其后面包含 “hot water” 或 "cold porridge “的文档。
该案例不能匹配到"when it’s cold my favorite food is porridge”, 因为all_of 的 ordered 属性为true,即第二层 intervals中的match和any_of是由先后顺序的。

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

2.2 match query

match 查询返回匹配到指定 text, number, date or boolean value 的文;其中指定的text会先被分析,然后再参加匹配.该查询是执行全文检索的标准查询,包括选择模糊匹配。

该查询顶层参数为field,子参数包括query 和 很多其它可选择参数。

GET /_search
{
    "query": {
        "match" : {
            "message" : {
                "query" : "this is a test"
            }
        }
    }
}
match 查询也可以将field 和 查询参数结合在一起,从而简化查询语法:
GET /_search
{
    "query": {
        "match" : {
            "message" : "this is a test"
        }
    }
}

match 查询最终会被转化为bool类型的查询,其查询的string会被解析,并构建成多个terms 查询,多个查询直接默认是or关系,该关系可以通过operator 来设置。

2.3 match_bool_prefix query

match_bool_prefix query 查询会分析其输入,并根据input中的terms构建一个bool 查询。其中最后一个term被用来做为prefix查询,其它的每个term都会单独构建一个term查询。
其顶层参数为field,子参数包括query 和 analyzer(可省略), analyzer 默认和 index 时候的analyzer相同。

GET /_search
{
   "query": {
       "match_bool_prefix" : {
           "message" : "quick brown f"
       }
   }
}
此处message字段中的 "quick brown f" 将被分解为 quick,brown,f 等3个terms,其中quick 和 brown 被用来构建2个terms 查询,f被用来构建一个prefix 查询,构建的查询如下:
GET /_search
{
   "query": {
       "bool" : {
           "should": [
               { "term": { "message": "quick" }},
               { "term": { "message": "brown" }},
               { "prefix": { "message": "f"}}
           ]
       }
   }
}
该查询和match_phrase_prefix 重要不同之处在于:match_phrase_prefix 匹配各个terms为一个短语(存在顺序), 但是match_bool_prefix query  可以在任何位置匹配其terms。
因此,该查询可以匹配到 quick brown fox、brown fox quick、quick、brown、以f开头的term,并且以上匹配的项可以存在于任何位置。

2.4 match_phrase query

该查询会分析 text,并基于分析的text创建短语查询。

GET /_search
{
    "query": {
        "match_phrase" : {
            "message" : "this is a test"
        }
    }
}
或者
GET /_search
{
    "query": {
        "match_phrase" : {
            "message" : {
                "query" : "this is a test",
                "analyzer" : "特定的分词器", # 可选参数
                "zero_terms_query": "none" # 可选参数
            }
        }
    }
}

2.5 match_phrase_prefix query

该查询返回包含特定短语(前缀)的文档,其中query的string中最后一个项表示前缀信息。

其顶层参数field,子参数包括 query、analyzer、max_expansions、slop 和 zero_terms_query。

以下案例将会匹配到包含 quick brown fox 或 two quick brown ferrets的文档,但是不会匹配到 the fox is quick and brown,因为该查询中的query 的字符串是一个整体。

GET /_search
{
    "query": {
        "match_phrase_prefix" : {
            "message" : {
                "query" : "quick brown f"
            }
        }
    }
}

除了基本查询外,该查询可以用来实现输入补全。

2.6 multi_match query

multi_match 查询基于match查询来构建查询,并允许多个字段参与查询,其中field字段值可以用一些基础的通配符,例如 *_name。

其顶层参数包括 query、fields、type和tie_breaker;
type 有best_fields、most_fields、cross_fields、phrase、phrase_prefix、bool_prefix 几个可选值,每个值都定义来一种不同的查询方法。

GET /_search
{
  "query": {
    "multi_match" : {
      "query":    "this is a test", 
      "fields": [ "subject", "message" ] 
    }
  }
}

2.7 common terms query

common terms query 是一个使用停用符(stopwords)不错选择,通过考虑停用符来提高准确度和召回率,且不用牺牲查询性能。
问题起源:
在一个查询中,每个数据项都有一个代价,“The brown fox” 需要3个term类型的查询, 且每个查询都会基于索引中所有的文档执行查询。然而the的频率很高,可能会匹配到很多文档,因此它的向比另外2个terms的影响低。
早起解决方案为:忽略高频的terms, 把the 视作停用次,从而能减少索引大小,并且能减少需要执行的terms类型查询任务。
但实际上,停用此影响虽然很小,但是有时候也很重要。如果去掉停用此,将会降低准确率,并且不能区分 “happy” 和 "not happy"之类的查询,还会失去回召率(无法搜索到 “The The” or “To be or not to be” 之类的查询).

解决方法:
common terms query 把 query terms 分为2组: 更加重要的 (低频数据项) 和 不太重要的 (高频数据项,包括之前的停用词).
第一阶段搜索更加重要类型的数据项,这些数据项出现在少数文档中,对相关度的影响更大。
第二阶段搜索不太重要类型的数据项,这些数据项出现的频率高,对相关度的影响更加低。但是该阶段并不计算所有匹配文档的score,只计算出现在第一阶段文档中匹配文档的score。通过这种方式,高频词可以提高相关度计算,单不会导致低性能。

当一个query只包括高频数据项,那么所有的单个查询都会以 AND 的方式执行。此种情况下,可以通过设置 minimum_should_match 使多个term查询以 OR 的方式执行。
common terms query 可以通过 cutoff_frequency 参数将 terms 划分到高频或低频组中,其值可以通过绝对频率(>=1) 或者相对频率(0.0 … 1.0) 来指定。 (需要记住:文档频率是基于单个shard级别计算出来的,因为数据量足够大的时候单个shard的频率即可代表全局频率,具体原因已经在 Relevance is broken 中解释了)。
该查询最有趣的属性是其可以自动适应特定领域的停用词。例如,在视频相关的站点,用户不需要手动维护一个list,clip 和video会自动被视为停用词,

在以下案例中,数据项的文档频率大于 0.1% (eg “this” and “is”)就会被视为普通的数据项。

GET /_search
{
    "query": {
        "common": {
            "body": {
                "query": "this is bonsai cool",
                "cutoff_frequency": 0.001
            }
        }
    }
}

除了 cutoff_frequency 参数外,还可以通过 minimum_should_match (high_freq, low_freq), low_freq_operator (default “or”) and high_freq_operator (default “or”) 等参数来调整查询方式。
以下案例中通过设置 low_freq_operator 为 and,低频term将会以 must的形式来执行查询。

GET /_search
{
    "query": {
        "common": {
            "body": {
                "query": "nelly the elephant as a cartoon",
                "cutoff_frequency": 0.001,
                "low_freq_operator": "and"
            }
        }
    }
}
等价为:
GET /_search
{
    "query": {
        "bool": {
            "must": [
            { "term": { "body": "nelly"}},
            { "term": { "body": "elephant"}},
            { "term": { "body": "cartoon"}}
            ],
            "should": [
            { "term": { "body": "the"}},
            { "term": { "body": "as"}},
            { "term": { "body": "a"}}
            ]
        }
    }
}

2.8 query_string query

该查询使用一种严格的语法来解析query string,基于这些query string返回查询文档。
其基于操作符,用一种特定的语法来解析和分离指定的query string,例如使用 AND 或者NOT。在返回匹配文档前,该查询会先分析每一个被分离的text。
用户可以通过 query_string 查询来创建复杂的搜索,该搜索不仅可以包含通配符,也可以对多个字段就行查询。该查询使用方式虽然很多,但其使用比较严格,一旦查询语法格式不对就报错。

以下案例将 query_string分为 new york city 和 big apple 2部分,然后再分别将两部分解析为对应的tokens,然后执行查询并返回符合要求匹配文档。

GET /_search
{
    "query": {
        "query_string" : {
            "query" : "(new york city) OR (big apple)",
            "default_field" : "content"
        }
    }
}

Query string 有很多语法要求,此处记录一些常见的语法:

  1. Field names
    字段名称有如下6种形式,内容较简单暂时翻译。
    1)where the status field contains active
    status:active
    2)where the title field contains quick or brown
    title:(quick OR brown)
    3)where the author field contains the exact phrase “john smith”
    author:“John Smith”
    4)where the first name field contains Alice (note how we need to escape the space with a backslash)
    first\ name:Alice
    5)where any of the fields book.title, book.content or book.date contains quick or
    brown (note how we need to escape the * with a backslash):
    book.*:(quick OR brown)
    6)where the field title has any non-null value:
    _exists_:title
  2. Wildcards
    通配符可以作用于单个数据项上面,例如用 ? 来代表单个字符,用 * 代替或者多个字符。
    但是通配符执行效率比较低,而且非常耗费资源,因此尽量少用或者不用统配符。
    注意:
    “field:*” 会匹配这类空值的数据 {“field”: “”}, 而不会匹配字段不存在或显式设置为null值的数据 {“field”: null};
    *ing 类型的通配符非常占用资源,其会导致索引中所有的项都会被检测;
  3. Regular expressions
    通过斜杠/的方式,可以将正则表达嵌入到query_string 中。相关正则见:es 中支持一些正则 Regular expression syntax.
    例如 name:/joh?n(ath[oa]n)/ 可以匹配到 johnathon 或johnathan
    注意:
    /.*n/ 类似的正则表达应该少用,因为其会导致索引中所有的项都会被访问;
  4. Fuzziness
    可以通过模糊操作符 ~ 来实现模糊匹配,即:可以匹配相似的数据项。
    quikc~ brwn~ foks~
    该方式使用Damerau-Levenshtein distance来查看所有的数据项,且允许最多2个变化。此处变化指的是插入、删除、替换一个字符,或者交换两个相邻的字符。
    默认的编辑距离为2,但是时间一个编辑距离也足以解决80%的拼写错误;因此可以通过 quikc~1 的方式设置模糊匹配的编辑距离为1。
  5. Proximity searches
    query_string 也支持邻近搜索,即相近的字符串即便顺序不相同也可以被匹配到。同模糊搜索一样,邻近搜索也可以指定编辑距离,但其只对短语有效。例如: “fox quick”~5,其编辑距离为5.
    该查询中,字段中的文本越接近原始顺序,它的相关度就越高。以上面为例,“quick fox” 就比"quick brown fox"的相关性更大。
  6. Ranges
    范围查询可以用于日期、数字、字符串类型的字段;可以使用方括号来包含指定范围的边界[min TO max],用大括号来排查指定范围的边界 {min TO max}。范围查询有如下7种常见的使用方式:
    1)All days in 2012:
    date:[2012-01-01 TO 2012-12-31]
    2)Numbers 1…5
    count:[1 TO 5]
    3)Tags between alpha and omega, excluding alpha and omega:
    tag:{alpha TO omega}
    4)Numbers from 10 upwards
    count:[10 TO ]
    5)Dates before 2012
    date:{
    TO 2012-01-01
    6)Numbers from 1 up to but not including 5 (方括号和大括号可以混合使用)
    count:[1 TO 5}
    7)Ranges with one side unbounded can use the following syntax:
    age:>10
    age:>=10
    age:<10
    age:<=10
    age:(>=10 AND <20)
    age:(+>=10 +<20)
  7. Boosting
    使用 boost 操作符 ^ 是一个数据项比其它数据向相关性更高. 例如,如果我们希望找到所有于foxes相关的文档,并且更加关注quick foxes,那么可以通过 quick^2 fox 来提高quick的相关性。
    boost 默认值为 1,其可以是如何正浮点数字,若boost在 0 and 1 之间则会降低其相关度.
    boost 参数也可以用于query_string 中的短语或群组; 例如:“john smith”^2 (foo bar)^4
  8. Boolean operators
    默认情况下,所有数据项都是可选的,只要一项匹配到即可。但是实际上很多过滤控制,因此可以使用bool操作符。
    + 表示该数据项必须存在,- 表示该数据项必然不存在,无+ - 限制的表示是可选项。
    例如:quick brown +fox -news 表示:
    fox 必须存在,news不存在,quick 和 brown 是可选的(它们的存在会增加相关性)。
    除了+ - 外,bool操作符也支持 AND, OR and NOT (&&, || and !),但是其不一定符合一般优先级规则(they do not honor the usual precedence rules),因此使用多个操作符的时候一般需要配置大括号。
    上述案例可以进一步表示为:
    ((quick AND fox) OR (brown AND fox) OR fox) AND NOT news
    也可以通过dsl形式表示为:
    {
        "bool": {
            "must":     { "match": "fox"         },
            "should":   { "match": "quick brown" },
            "must_not": { "match": "news"        }
        }
    }
    
  9. Reserved characters
    es 中有一些保留的字符,该字符具备一些操作符的功能,因此使用的时候需要加上斜杠。例如:要搜索 (1+1)=2,则应该表示为 (1+1)=2。
    常见的保留字符包括:+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /

2.9 simple_query_string query

基于指定的query string返回相关文档, 该query字符串使用 limited but fault-tolerant 语法解析器。
该查询基于特定的操作符,使用一种简单的语法来解析并分离指定的查询字符串为很多个单独的数据项。然后再独立地分析每一个数据项,最后返回匹配的文档。
该查询比 query_string 限定更强,但当出现无效语法的时候其报错,而是直接忽略掉无效的query字符串。
其常见顶层参数包括:query(必选), fields, default_operator, all_fields, flags 等.

GET /_search
{
  "query": {
    "simple_query_string" : {
        "query": "\"fried eggs\" +(eggplant | potato) -frittata",
        "fields": ["title^5", "body"],
        "default_operator": "and"
    }
  }
}

simple_query_string 查询支持如下操作符:

  • + signifies AND operation
  • | signifies OR operation
  • - negates a single token
  • " wraps a number of tokens to signify a phrase for searching
  • * at the end of a term signifies a prefix query
  • ( and ) signify precedence
  • ~N after a word signifies edit distance (fuzziness)
  • ~N after a phrase signifies slop amount

3 说明

  1. 参考文档
    full-text-queries
    更多DSL 查询内容见elk笔记13–Query DSL
  2. 测试环境
    本文测试案例对应的 es 版本为7.2.1
    测试数据为kibana自带数据,Home->Add data->Sample data->Sample eCommerce orders
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值