乐趣区

关于elasticsearch:ES系列之原理copyto用好了这么香

写在后面

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"
      ]
    }
  }
}
退出移动版