天天看点

Elasticsearch term查询与match查询区别

作者:贵哥说Java创业

term 查询

精确值查询

查询 price 字段等于6000的文档

# 新增三个文档
PUT /ad/_doc/1
{
    "name":"phone 8",
    "price":6000,
    "color":"white",
    "ad":"this is a white phone",
    "label":[
        "white",
        "nice"
    ]
}

PUT /ad/_doc/2
{
    "name":"xiaomi 8",
    "price":4000,
    "color":"red",
    "ad":"this is a red phone",
    "label":[
        "white",
        "xiaomi"
    ]
}

PUT /ad/_doc/3
{
    "name":"huawei p30",
    "price":5000,
    "color":"white",
    "ad":"this is a white phone",
    "label":[
        "white",
        "huawei"
    ]
}

           

查询price字段等于6000的文档

GET /ad/_search
{
    "query":{
        "term":{
            "price":{
                "value":"6000"
            }
        }
    }
}

# 输出结果
{
    "took":0,
    "timed_out":false,
    "_shards":{
        "total":1,
        "successful":1,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":{
            "value":1,
            "relation":"eq"
        },
        "max_score":1,
        "hits":[
            {
                "_index":"ad",
                "_type":"_doc",
                "_id":"1",
                "_score":1,
                "_source":{
                    "name":"phone 8",
                    "price":6000,
                    "color":"white",
                    "ad":"this is a white phone",
                    "label":[
                        "white",
                        "nice"
                    ]
                }
            }
        ]
    }
}           

查询 name 字段等于 phone 8 的文档

GET /ad/_search
{
    "query":{
        "term":{
            "name":{
                "value":"phone 8"
            }
        }
    }
}

# 输出结果
{
    "took":0,
    "timed_out":false,
    "_shards":{
        "total":1,
        "successful":1,
        "skipped":0,
        "failed":0
    },
    "hits":{
        "total":{
            "value":0,
            "relation":"eq"
        },
        "max_score":null,
        "hits":[

        ]
    }
}           

默认情况下,Elasticsearch 针对 text 字段的值进行解析分词,这会使查找 text 字段值的精确匹配变得困难。要搜索 text 字段值,需改用 match 查询。

为什么没有查到 phone 8 的这个文档呢,这里需要介绍一下 term 的查询原理:

term 查询会去倒排索引中寻找确切的 term ,它并不会走分词器,只会去匹配倒排索引 ,而 name 字段的type 类型是 text ,会进行分词,将 phone 8 分为 phone 和 8 ,我们使用 term 查询 phone 8 时倒排索引中没有 phone 8 ,所以没有查询到匹配的文档。

term 查询与 match 查询的区别:

  1. term 查询时,不会分词,直接匹配倒排索引。
  2. match 查询时会进行分词,查询 phone 8 时,会先分词成 phone 和 8 ,然后去匹配倒排索引,所以结果会将 phone 8 和 xiaomi 8 两个文档都查出来。

还有一点需要注意,因为 term 查询不会走分词器,但是会去匹配倒排索引,所以查询的结构就跟分词器如何分词有关系,比如新增一个 /ad 的文档, name 字段赋值为 Oppo ,这时使用 term 查询 Oppo 不会查询出文档,这时因为es默认是用的 standard 分词器,它在分词后会将单词转成小写输出,所以使用 Oppo 查不出文档,使用小写 oppo 可以查出来。

# 新增文档
PUT /ad/_doc/4
{
    "name":"Oppo",
    "price":3999,
    "color":"white",
    "ad":"this is a white phone",
    "label":[
        "white",
        "Oppo"
    ]
}

# 使用Oppo查询不出文档,改成oppo可以查出新添加的文档
GET /ad/_search
{
    "query":{
        "term":{
            "name":{
                "value":"Oppo"
            }
        }
    }
}

           

这里说的并不是想让你了解 standard 分词器,而是要get到所有像 term 这类的查询结果跟选择的分词器有关系,了解选择的分词器分词方式有助于我们编写查询语句。

继续阅读