Skip to content

Latest commit

 

History

History
261 lines (205 loc) · 5.48 KB

query.md

File metadata and controls

261 lines (205 loc) · 5.48 KB

查询

首先我们建立一个索引方便讲解,索引对应的mappings如下所示。

{
    "query_test_index": {
        "mappings": {
            "properties": {
                "keyword_field": {
                    "type": "keyword"
                },
                "text_field": {
                    "type": "text",
                    "analyzer": "standard"
                }
            }
        }
    }
}

词级别查询

词级别查询在查询前不会对查询词进行分词。

Term Query

对于未分词的字段,Term Query要求查询的目标值和文档中字段的值完全一致。比如下面这个查询,查询的目标值是"hello world",当且仅当文档的keyword_field字段的值是"hello world"时才能进行匹配。

// 文档
{
    "keyword_field": "hello world"
}

// 查询
{
    "query": {
        "term" : { "keyword_field" : "hello world" }
    }
}

对于分词的字段,Term Query要求字段进行分词后的值至少有一个和要查询的目标值完全一致。下面的查询是无法查到结果的,这是因为text_field分词后得到的是"hello"和"world",不包含目标值"hello world",因此不匹配。

// 文档
{
    "text_field": "hello world"
}

// 查询
{   "query": {
        "term" : { "keyword_field" : "hello world" }
    }
}

如果我们把查询的目标值改成"hello"就可以查出该条数据。

{   "query": {
        "term" : { "keyword_field" : "hello" }
    }
}

Wildcard Query

Wildcard Query支持通配符,?匹配一个字符,*匹配0个或多个字符。

以下查询可以匹配到结果。

// 文档
{
    "keyword_field": "I like driving"
}

// 查询
{
    "query": {
        "wildcard" : { "keyword_field" : "I lik*" }
    }
}

以下查询也可以匹配到结果。

// 文档
{
    "text_field": "I like driving"
}

// 查询
{
    "query": {
        "wildcard" : { "text_field" : "lik*" }
    }
}

但是下面这个查询查不到结果,这是因为Wildcard Query不会对查询词进行分词,而text_field字段的值会被解析成"I"、"like"、"driving",都无法和"I lik*"匹配。

// 文档
{
    "text_field": "I like driving"
}

// 查询
{
    "query": {
        "wildcard" : { "text_field" : "I lik*" }
    }
}

Prefix Query

Prefix Query会根据输入的前缀去匹配文档。

// 文档
{
    "text_field": "I like driving and reading"
}

// 查询
{
    "query": {
        "prefix" : { "text_field" : "dri" }
    }
}

// 文档
{
    "keyword_field": "I like driving and reading"
}

// 查询
{
    "query": {
        "prefix" : { "keyword_field" : "I like" }
    }
}

Regexp Query

Regexp Query允许在查询词中使用正则表达式。

// 文档
{
    "text_field": "I like driving"
}

// 查询
{
    "query": {
        "regexp" : { "text_field" : "driving|reading" }
    }
}

// 文档
{
    "keyword_field": "I like driving"
}

// 查询
{
    "query": {
        "regexp" : { "keyword_field" : "I like .*" }
    }
}

Fuzzy Query

Fuzzy Query可以匹配单词和查询词相似的文档,比如"surprize"可以匹配到"surprise"。

// 文档
{
    "text_field": "I like driving and reading"
}

// 查询
{
    "query": {
        "fuzzy" : { "text_field" : "dri" }
    }
}

全文查询

全文查询是指在查询前先对查询词进行分词的查询。

Match Query

Match Query会在查询之前对目标词进行分词,比如用"hello world"可以匹配到"hello, my world",这是因为"hello world"进行分词后会被分为"hello"和"world"。需要注意的是文档中只需要包含一个经过分词后的搜索关键字就能匹配查询,比如"hello god"也可以匹配到"hello, my world",尽管后者不包含"god"。

// 文档
{
    "text_field": "hello, my world"
}

// 查询
{
    "query": {
        "match" : { "text_field" : "hello world" }
    }
}

Match Phrase Query

Match Phrase Query会对把输入的短语作为一个整体进行查询,查询短语中所有的单词都包含,并且单词的顺序也相同的文档才会匹配,比如"I like driving"可以匹配到文档"I like driving and reading",不能匹配到"I like reading"。

// 文档
{
    "text_field": "I like driving and reading"
}

// 查询
{
    "query": {
        "match_phrase" : { "text_field" : "I like driving" }
    }
}

如果我们希望"I like reading"可以匹配到"I like driving and reading",可以使用slop参数,它表示短语中单词之间的间距的最大范围,比如slop是2,那么就表示两个单词之间最多允许有另外的2个单词。当slop是2时,"I like reading"就可以匹配到"I driving driving and reading",这是因为文档中"reading"和"like"之间差了两个单词的距离。slop的默认值是0。

// 查询
{
  "query": {
    "match_phrase": {
      "text_field": {
        "query": "I like reading",
        "slop": 2
      }
    }
  }
}

Match Phrase Prefix Query

Match Phrase Prefix Query和Match Phrase Query类似,只是对于短语中的最后一个单词可以进行前缀匹配,比如"I like d"可以匹配到"I like driving and reading"。该查询方式同样支持slop参数,当slop设置为2时,"I like r"可以匹配到"I like driving and reading"。

参考

  1. 《Elasticsearch Query DSL 整理总结(三)—— Match Phrase Query 和 Match Phrase Prefix Query》