天天看點

Elasticsearch term查詢與match查詢差別

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 這類的查詢結果跟選擇的分詞器有關系,了解選擇的分詞器分詞方式有助于我們編寫查詢語句。

繼續閱讀