专栏首页犀牛饲养员的技术笔记ES系列之原理copy_to用好了这么香

ES系列之原理copy_to用好了这么香

写在前面

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"
      ]
    }
  }
}

本文分享自微信公众号 - 犀牛饲养员的技术笔记(coder_start_up),作者:siwuxie18

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ES对磁盘的要求都有哪些,大部分你可能不知道

    有一个问题被关注的比较少,就是ES对本地磁盘的占用情况。有人可能觉得这个问题的答案显而易见,不就是ES软件本身占用的空间,还有索引数据持久化占用的磁盘空间,另外...

    用户7634691
  • ES分页看这篇就够了

    我们使用mysql的时候经常遇到分页查询的场景,在mysql中使用limit关键字来实现分页。比如下面的示例。

    用户7634691
  • 带你认识线程安全的集合操作

    简单来讲,我们平时经常使用的ArrayList不是线程安全的。我们通过使用 Collections.synchronizedList 来包装一个线程安全的Arr...

    用户7634691
  • python中的内置函数(双下划线) 原

    如果我们是直接执行某个.py文件的时候,该文件中那么”__name__ == '__main__'“是True,但是我们如果从另外一个.py文件通过import...

    晓歌
  • 【Python基础】函数的返回

    很多时候,函数并非直接输出,相反,它可以处理一些数据,并返回一个值或者一组值,称之为返回值。

    DataScience
  • Python操作Redis的最佳实践

    致码DevOps
  • python操作数据库

    pip install redispy 参考:https://www.cnblogs.com/john-xiong/p/12089103.html

    sofu456
  • Python之Django自动实现html代码(下拉框,数据选择)

    补充知识:django使用模板实现下拉菜单,菜单内容读取后台动态填充,并动态设置默认值

    砸漏
  • Python 分布式缓存之Reids数据类型操作详解

    redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护...

    砸漏
  • Python操作redis数据库

      redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、se...

    马一特

扫码关注云+社区

领取腾讯云代金券