ES系列之原来copy

tech2025-04-28  6

写在前面

Elasticsearch(以下简称ES)有个copy_to的功能,之前在一个项目中用到,感觉像是发现了一个神器。这个东西并不是像有些人说的是个语法糖。它用好了不但能提高检索的效率,还可以简化查询语句。

基本用法介绍

直接上示例。

先看看mapping,

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这个字段查询了,

GET my_index/_search { "query": { "match": { "full_name": { "query": "John Smith", "operator": "and" } } } }

查询结果如下:

"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的话,我们需要指定两个字段查询,类似如下的语句:

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" ] } } }
最新回复(0)