Elasticsearch(如下简称ES)有个copy_to
的功能,以前在一个项目中用到,感受像是发现了一个神器。这个东西并非像有些人说的是个语法糖。它用好了不但能提升检索的效率,还能够简化查询语句。app
直接上示例。ui
先看看mapping,code
PUT my_index { "mappings": { "properties": { "first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" }, "full_name": { "type": "text" } } } }
first_name和last_name都指定了copy_to
,表示他们这两个字段的值都会复制到full_name上。写入两条文档看看,文档
PUT my_index/_doc/1 { "first_name": "John", "last_name": "Smith" } PUT my_index/_doc/2 { "first_name": "Tom", "last_name": "Cruise" }
而后咱们在查询的时候,就能够指定从full_name这个字段查询了,it
GET my_index/_search { "query": { "match": { "full_name": { "query": "John Smith", "operator": "and" } } } }
查询结果以下:io
"hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.3862944, "hits" : [ { "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_score" : 1.3862944, "_source" : { "first_name" : "John", "last_name" : "Smith" } } ] }
若是没有使用copy_to的话,咱们须要指定两个字段查询,相似以下的语句:ast
GET my_index/_search { "query": { "bool": { "must": [ {"match": { "first_name": "John" }}, {"match": { "last_name": "Smith" }} ] } } }
两种方式查询的结果是同样的。效率
聊完了基本用法,来看看一些高级的功能。假如说咱们想获取full_name的内容,有些业务场景下,咱们会须要返回这个字段,怎么办呢?其实很简单,以下所示,咱们在设置mapping的时候加上store:true
便可。原理
PUT my_index { "mappings": { "properties": { "first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" }, "full_name": { "type": "text", "store": true } } } }
而后再写入文档,咱们能够经过下面的语句查询到full_name的内容。进阶
GET my_index/_doc/1?stored_fields=full_name
得的结果是:
{ "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "fields" : { "full_name" : [ "John", "Smith" ] } }
若是你没有指定store
为true,查询的结果是这样的:
{ "_index" : "my_index", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true }
再来看另一个问题。把上面的mapping改一下,text改成keyword,以下:
PUT my_index { "mappings": { "properties": { "first_name": { "type": "keyword", "copy_to": "full_name" }, "last_name": { "type": "keyword", "copy_to": "full_name" }, "full_name": { "type": "keyword", "store": true } } } }
而后仍是写入上面示例的两条数据。当咱们用通用的查询语句查询时发现搜索不到结果了,这是为啥呢?我这里先给出解决方案,可是不解释原理,有兴趣的能够思考下。
用下面两个查询语句均可以查询到结果,你以为是什么缘由?
GET my_index/_search { "query": { "bool": { "must": [ {"term": { "first_name": { "value": "John" } }}, {"term": { "last_name": { "value": "Smith" } }} ] } } } GET my_index/_search { "query": { "terms": { "full_name": [ "John", "Smith" ] } } }