许吉友 - 运维

ES 之 Query DSL 二

这篇文章来学习 ES 的全文检索,可以学习如何检索一篇文章的任意内容。在索引过程中,ES 会使用分词器对文档进行分词处理。

intervals 查询

首先先来一个例子,先插入两条数据:

POST article/_doc/1
{
  "content": "my favorite food is cold porridge but not when it's cold my favorite food is porridge"
}

POST article/_doc/2
{
  "content": "my favorite food is cold porridge but not when it's cold my favorite food is hot water"
}

然后使用 intervals 进行查询:

POST article/_search
{
  "query": {
    "intervals" : {
      "content" : {
        "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" } }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.5,
    "hits" : [
      {
        "_index" : "article",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.5,
        "_source" : {
          "content" : "my favorite food is cold porridge but not when it's cold my favorite food is hot water"
        }
      },
      {
        "_index" : "article",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.3333333,
        "_source" : {
          "content" : "my favorite food is cold porridge but not when it's cold my favorite food is porridge"
        }
      }
    ]
  }
}

可以看到 ,intervals 下面跟的是文档的字段名称,随后跟一个 all_of ,这里除了 all_of,还可以跟 match 、prefix、wildcard、any_of、filter。

每种匹配模式下面使用的子句是不一样的,下面分别来介绍。

all_of

all_of 是其他 interval 的组合,它包含以下几个子句:

match

prefix

前缀匹配,匹配一个单词的前缀,比如 favorite ,可以前缀搜索 favo,最多128个字母

wildcard

通配符匹配,最多128个字母

any_of

任何一个子模式被匹配了都返回

filter

过滤器,不影响分数。

match 查询

匹配查询是执行全文搜索的标准查询,包括模糊匹配选项。

先看例子:

GET /_search
{
    "query": {
        "match" : {
            "message" : {
                "query" : "this is a test"
            }
        }
    }
}

match 下面是一个文档字段,这里的字段是 message,字段下面包含以下子句

match_bool_prefix 查询

示例:

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

相当于:

GET /_search
{
    "query": {
        "bool" : {
            "should": [
                { "term": { "message": "quick" }},
                { "term": { "message": "brown" }},
                { "prefix": { "message": "f"}}
            ]
        }
    }
}

match_bool_prefix 又一个子句为 analyzer ,可以指定分词器。

match_phrase 查询

match_phrase 是短语查询,类似于上面的 intervals 的 max_gaps 为 0。

示例:

GET /_search
{
    "query": {
        "match_phrase" : {
            "message" : "this is a test"
        }
    }
}

match_phrase_prefix 查询

match_bool_prefix 和 match_phrase 的联合版:

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

multi_match 查询

match 只能查一个字段,multi_match 可以查询多个字段

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

字段名也可以使用通配符

GET /_search
{
  "query": {
    "multi_match" : {
      "query":    "Will Smith",
      "fields": [ "title", "*_name" ] 
    }
  }
}

如果 fields 为空,则将对所有字段进行搜索

好了,到此为止,所有的查询就都有涉及了。后面的 Common term Query 在 7.3.0 版本中标明过期了,而Query String 和 Simple Query String 可能会带来注入,所以不学习了,关于全文索引,前面介绍的完全够用。