ElasticSearch 6.5 keyword 和 text 字段差异及查询

  • keyword 和 text 字段类型
    首先,ES 索引的相关信息可以参见建立索引的命令。
curl -u user:password \
-X PUT "http://host:port/my_test_index" \
-H 'Content-Type: application/json' -d'{
  "settings":{"index":{"number_of_shards":20,"number_of_replicas":1,"max_result_window":1000}},
  "mappings":{
      "_doc":{
          "properties":{
            "shop_id":{"type":"long"},
            "shop_name":{"type":"keyword"},
            "business_desc":{"type":"text"},
            "members":{"type":"nested",
                "dynamic":false,
                "properties":{
                    "member_id":{"type":"long"},
                    "member_name":{"type":"keyword"}
                }
            }
          }
      }
  }
}'

索引的 mapping 信息表明这是一个店铺及其会员信息的索引,shop_id 是店铺 id,shop_name 是店铺名称,business_desc 是店铺的经营内容描述,members 是一个 nested 类型的字段,代表该店铺的会员列表。
shop_name 字段的类型是 keyword,ES 在为该字段建立索引的时候,会为整个字段值建立索引,而不会对其进行分词,例如某个店铺名称是“王大锤的创意品小店”,ES 的倒排索引会建立针对“王大锤的创意品小店”的倒排索引。business_desc 字段类型是 text,ES 在为该字段建立索引时,会首先对字段值进行分词(使用默认的分词器,或用户指定的分词器),例如某个店铺的经营描述是“创意品,饰品,房间挂件,汽车挂件”,ES 会为创意品、饰品、房间、挂件、汽车、挂件等都建立倒排索引。
keyword 表明字段值是一个供匹配的名词,text 表明字段包含多个供匹配名词。
可以使用如下命令将上述文档写入 ES 索引。

curl -u user:password \
-X PUT "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "ship_id" : 1234554321,
  "shop_name": "王大锤的创意品小店",
  "business_desc": "创意品,饰品,房间挂件,汽车挂件",
  "members" : [
    {
      "member_id" :1,
      "member_name" :  "飞天贵妃"
    },
    {
      "member_id" : 2,
      "member_name" :  "Mary"
    }
  ]
}
}'
  • keyword 和 text 字段匹配策略
    使用 ES 进行查询时,常见的匹配策略有 term、match(match_phrase)、wildcard 等。在 keyword 和 text 字段上进行文档检索时,他们有着不同的匹配方式。term 将被检索词作为一个名词在指定字段上进行检索(不对被检索词进行分词操作),match 则将被检索词进行分词后在指定
    字段上进行检索。
    例如,在上述索引上执行下面几个检索,其结果分别如下。
1) 匹配到 0 个文档,因为 shop_name 只有一个 "王大锤的创意品小店" 倒排索引
curl -u user:password \
-X GET "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "query":{
		"bool":{
			"filter":{"match":{"shop_name":"王大锤"}}
		}
  }
}'
2) 匹配到 0 个文档,因为 shop_name 只有一个 "王大锤的创意品小店" 倒排索引
curl -u user:password \
-X GET "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "query":{
		"bool":{
			"filter":{"term":{"shop_name":"王大锤"}}
		}
  }
}'
3) 匹配到 1 个文档,对倒排索引进行通配符匹配,找到包含 王大锤 的索引文档
curl -u user:password \
-X GET "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "query":{
		"bool":{
			"filter":{"wildcard":{"shop_name":"*王大锤*"}}
		}
  }
}'
4) 匹配到 1 个文档,match 会得检索词进行分词,将 "王大锤创意品" 分词为 "王大锤" 、"创意品" 等进行匹配。而 business_desc 的类型是 text,ES 会对字段值进行分词后建立倒排索引,因此对该字段建立的索引会有 "创意品","饰品","房间","挂件","汽车"等,因此能匹配到检索词"创意品"。注意,ES 实际的分词策略可能不是这样,这里只是示例。
curl -u user:password \
-X GET "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "query":{
		"bool":{
			"filter":{"match":{"business_desc":"王大锤创意品"}}
		}
  }
}'
5) 匹配到 0 个文档,term 不会检索词进行分词,而business_desc字段的索引中是没有"王大锤创意品"这个词的。
curl -u user:password \
-X GET "http://host:port/my_test_index/_doc/1" \
-H 'Content-Type: application/json' -d'{
  "query":{
		"bool":{
			"filter":{"term":{"business_desc":"王大锤创意品"}}
		}
  }
}'

参见 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

你可能感兴趣的:(大数据)