带你读《Elastic Stack 实战手册》之38:——3.4.2.19.copy_to

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 带你读《Elastic Stack 实战手册》之38:——3.4.2.19.copy_to

3.4.2.19.copy_to


创作人:章海怒

审稿人:欧阳楚才

 

在写入数据时对写入的内容进行拼贴,组合成一个全新的数据;也就是说固定的数据的拼接可以在 ES 中先完成,而不需要在查询数据时针对查询做繁杂的拼接。

 

关键词:copy_to

 

copy_to 参数允许将多个字段的值复制到一个单独的字段中,然后可以将其作为单个字段进行查询。

 

使用场景:copy_to 的一个常见用法就是用来减少搜索的字段数来提升搜索的效率;查询的字段越多,理论上 ES 的返回就越慢。多字段查询的时候,一种常见的性能优化方式是通过 copy_to 将多个查询字段的值合并为1个字段(数据的简单拼贴),通过合并后的字段进行查询,这样可以有效避免 multi_match 的使用,并且可以使得效率提高。

 

例如:

{
    "user": "双榆树-张三",
    "message": "今儿天气不错啊,出去转转去",
    "uid": 2,
    "age": 20,
    "city": "北京",
    "province": "北京",
    "country": "中国",
    "address": "中国北京市海淀区",
    "location": {
        "lat": "39.970718",
           "lon": "116.325747"
    }
}

在这里,我们可以看到在这个文档中,有这样的几个相关字段:city、province、country ,如果想放在一起搜索,一种方法我们可以在 must 子句中使用 should 子句查询。这种方法写起来比较麻烦并且性能比较低。这个时候,我们就可以考虑用 copy_to 将3个字段糅合成一个字段来搜索

 

例如:


PUT twitter
{
    "mappings": {
        "properties": {
            "address": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "age": {
                "type": "long"
            },
            "city": {
                "type": "keyword",
                "copy_to": "region"
            },
            "country": {
                "type": "keyword",
                "copy_to": "region"
            },
            "province": {
                "type": "keyword",
                "copy_to": "region"
            },
            "region": {
                "type": "text",
                "store": true
            },
            "location": {
                "type": "geo_point"
            },
            "message": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "uid": {
                "type": "long"
            },
            "user": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            }
        }
    }
}

我们通过 mapping 时声明 copy_to 的指定,把 city、 country 及 province 三个字段合并成为一个字段 region,但是这个 region 并不存在于我们文档的 source 里

 

我们录入一些样例数据:


POST _bulk
{ "index" : { "_index" : "twitter", "_id": 1} }
{"user":"双榆树-张三","message":"今儿天气不错啊,出去转转去","uid":2,"age":20,"city":"北京","province":"北京","country":"中国","address":"中国北京市海淀区","location":{"lat":"39.970718","lon":"116.325747"}}
{ "index" : { "_index" : "twitter", "_id": 2 }}
{"user":"东城区-老刘","message":"出发,下一站云南!","uid":3,"age":30,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区台基厂三条3号","location":{"lat":"39.904313","lon":"116.412754"}}
{ "index" : { "_index" : "twitter", "_id": 3} }
{"user":"东城区-李四","message":"happy birthday!","uid":4,"age":30,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区","location":{"lat":"39.893801","lon":"116.408986"}}
{ "index" : { "_index" : "twitter", "_id": 4} }
{"user":"朝阳区-老贾","message":"123,gogogo","uid":5,"age":35,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区建国门","location":{"lat":"39.718256","lon":"116.367910"}}
{ "index" : { "_index" : "twitter", "_id": 5} }
{"user":"朝阳区-老王","message":"Happy BirthDay My Friend!","uid":6,"age":50,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区国贸","location":{"lat":"39.918256","lon":"116.467910"}
{ "index" : { "_index" : "twitter", "_id": 6} }
{"user":"虹桥-老吴","message":"好友来了都今天我生日,好友来了,什么 birthday happy 就成!","uid":7,"age":90,"city":"上海","province":"上海","country":"中国","address":"中国上海市闵行区","location":{"lat":"31.175927","lon":"121.383328"}}

假如我们想搜索 country : 中国,province : 北京 这样的记录,我们可以只写如下的一条语句就可以了


GET twitter/_search
{
    "query": {
        "match": {
            "region": {
                "query": "中国 北京",
                "minimum_should_match": 4
            }
        }
    }
}

如果想查看 copy_to 的内容,就需要如例子中,显性的声明 region 这个字段 "store": true

声明以后就可以通过:

 

GET twitter/_doc/1?stored_fields=region

来查看对应region的内容,以上查询可以返回结果:

{
    "_index": "twitter",
    "_type": "_doc",
    "_id": "1",
"_version": 1,
  "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "fields": {
        "region": [
            "北京",
            "北京",
            "中国"
        ]
    }
}


小贴士:

 

1、copy_to 是值拷贝,也就是说拷贝之后 city ,provice 还是可以独立用于查询(与传统值拷贝不同的是,ES 更新时先查询出原来的文档,然后插入一条新文档,标记删除旧文档,所以copy_to 的字段在源字段更新时,会同时更新)。

2、copy_to 不可以嵌套使用。

3、可以拷贝至多个字段例如 "copy_to": [ "field_1", "field_2" ]。

4、copy_to 的字段本身包含类型的声明,支持不同类型的数据 copy_to 到同一字段,会有一次类型的转换。

5、copy_to 实际 copy 发生在数据写入时,会直接形成一个新的字段,所以 copy_to 实际会占用集群的磁盘、物理资源等。

 

本文部分内容参考自CSDN——Elastic 中国社区官方博客

 

 

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
测试技术 PHP 数据库
ThinkPHP6.0使用PHPUnit进行单元测试
ThinkPHP6.0使用PHPUnit进行单元测试
1016 0
ThinkPHP6.0使用PHPUnit进行单元测试
LabVIEW 在运行时初始化数组并允许用户编辑值
LabVIEW 在运行时初始化数组并允许用户编辑值
401 0
|
测试技术 PHP 数据库
ThinkPHP6.0使用PHPUnit进行单元测试
ThinkPHP6.0使用PHPUnit进行单元测试
519 0
ThinkPHP6.0使用PHPUnit进行单元测试
【vue2】vue2 实现手风琴效果,复制粘贴直接使用
【vue2】vue2 实现手风琴效果,复制粘贴直接使用
272 1
|
数据可视化 数据挖掘 知识图谱
精选:15款顶尖Python知识图谱(关系网络)绘制工具,数据分析的强力助手
这里有15款免费工具推荐:NetworkX(Python基础),Graph-tool(C++速度),Graphviz(可视化库),ipycytoscape(Jupyter集成),ipydagred3,ipySigma(NetworkX + Web),Netwulf(交互式),nxviz(Matplotlib绑定),Py3plex(复杂网络分析),Py4cytoscape(Python+Cytoscape),pydot(Graphviz接口),PyGraphistry(GPU加速),python-igraph,pyvis(交互式图形),SNAP(大规模网络分析)。绘制和理解网络图从未如此简单!
926 0
|
安全 Java 数据库连接
Springboot中启动器及自定义启动器
Springboot中启动器及自定义启动器
438 0
|
Unix C#
使用Inno Setup 制作软件安装包详细教程(与开发语言无关)
前言:关于如何制作一个软件安装包的教程,与编程语言无关。以下,请看详情~
1481 0
使用Inno Setup 制作软件安装包详细教程(与开发语言无关)
|
机器学习/深度学习 并行计算 TensorFlow
没有显卡怎么使用anaconda配置tensorflow深度学习环境
没有显卡怎么使用anaconda配置tensorflow深度学习环境
没有显卡怎么使用anaconda配置tensorflow深度学习环境
|
存储
Elastic实战: 通过bucket_sort针对聚合后结果实现分页、排序
elaticsearch中实现聚合操作十分常见,同时es本身存储的数据量一般都比较大,因此聚合结果数量通常都比较多,所以针对聚合结果进行分页,也是非常常见的需求
850 0
Elastic实战: 通过bucket_sort针对聚合后结果实现分页、排序