天天看點

[ElasticSearch]嵌套對象之嵌套類型

nested

類型是一種特殊的對象

object

資料類型(specialised version of the object datatype ),允許對象數組彼此獨立地進行索引和查詢。

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#1-%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E5%A6%82%E4%BD%95%E6%89%81%E5%B9%B3%E5%8C%96 1. 對象數組如何扁平化

内部對象

object

字段的數組不能像我們所期望的那樣工作。 Lucene沒有内部對象的概念,是以Elasticsearch将對象層次結構扁平化為一個字段名稱和值的簡單清單。 例如,以下檔案:

curl -XPUT 'localhost:9200/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d'
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}
'           

說明

user

字段被動态的添加為

object

類型的字段。

在内部其轉換成一個看起來像下面這樣的文檔:

{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}           

user.first

user.last

字段被扁平化為多值字段,并且

alice

white

之間的關聯已經丢失。 本文檔将錯誤地比對

user.first

alice

user.last

smith

的查詢:

curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}
'           

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#2-%E5%AF%B9%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E4%BD%BF%E7%94%A8%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5 2. 對對象數組使用嵌套字段

如果需要索引對象數組并維護數組中每個對象的獨立性,則應使用

nested

資料類型而不是

object

資料類型。 在内部,嵌套對象将數組中的每個對象作為單獨的隐藏文檔進行索引,這意味着每個嵌套對象都可以使用嵌套查詢

nested query

獨立于其他對象進行查詢:

curl -XPUT 'localhost:9200/my_index?pretty' -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "my_type": {
      "properties": {
        "user": {
          "type": "nested" 
        }
      }
    }
  }
}
'

curl -XPUT 'localhost:9200/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d'
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}
'           

user

字段映射為

nested

類型,而不是預設的

object

類型

curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "Smith" }} 
          ]
        }
      }
    }
  }
}
'           

此查詢得不到比對,是因為

Alice

Smith

不在同一個嵌套對象中。

curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "White" }} 
          ]
        }
      },
      "inner_hits": { 
        "highlight": {
          "fields": {
            "user.first": {}
          }
        }
      }
    }
  }
}
'           

此查詢得到比對,是因為

Alice

White

位于同一個嵌套對象中。

inner_hits

允許我們突出顯示比對的嵌套文檔。

輸出

{
    "took": 6,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 1.987628,
        "hits": [
            {
                "_index": "my_index",
                "_type": "my_type",
                "_id": "1",
                "_score": 1.987628,
                "_source": {
                    "group": "fans",
                    "user": [
                        {
                            "first": "John",
                            "last": "Smith"
                        },
                        {
                            "first": "Alice",
                            "last": "White"
                        }
                    ]
                },
                "inner_hits": {
                    "user": {
                        "hits": {
                            "total": 1,
                            "max_score": 1.987628,
                            "hits": [
                                {
                                    "_index": "my_index",
                                    "_type": "my_type",
                                    "_id": "1",
                                    "_nested": {
                                        "field": "user",
                                        "offset": 1
                                    },
                                    "_score": 1.987628,
                                    "_source": {
                                        "first": "Alice",
                                        "last": "White"
                                    },
                                    "highlight": {
                                        "user.first": [
                                            "<em>Alice</em>"
                                        ]
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        ]
    }
}           

嵌套文檔可以:

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#3-%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5%E5%8F%82%E6%95%B0 3. 嵌套字段參數

嵌套字段接受以下參數:

參數 描述
dynamic 是否将新屬性動态添加到現有的嵌套對象。共有

true

(預設),

false

strict

三種參數。
include_in_all Sets the default include_in_all value for all the properties within the nested object. Nested documents do not have their own _all field. Instead, values are added to the _all field of the main “root” document.
properties 嵌套對象中的字段,可以是任何資料類型,包括嵌套。新的屬性可能會添加到現有的嵌套對象。

備注

類型映射(

type mapping

)、對象字段和嵌套字段包含的子字段,稱之為屬性

properties

。這些屬性可以為任意資料類型,包括

object

和 

nested

。屬性可以通過以下方式加入:

  • 當在建立索引時顯式定義他們。
  • 當使用

    PUT mapping API

    添加或更新映射類型時顯式地定義他們。
  • 當索引包含新字段的文檔時動态的加入。

重要

由于嵌套文檔作為單獨的文檔進行索引,是以隻能在

nested

查詢,

nested

/

reverse_nested

聚合或者 

 的範圍内進行通路。

For instance, if a string field within a nested document has index_options set to offsets to allow use of the postings highlighter, these offsets will not be available during the main highlighting phase. Instead, highlighting needs to be performed via nested inner hits.

https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#4-%E9%99%90%E5%88%B6%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5%E7%9A%84%E4%B8%AA%E6%95%B0 4. 限制嵌套字段的個數

索引一個擁有100個嵌套字段的文檔,相當于索引了101個文檔,因為每一個嵌套文檔都被索引為一個獨立的文檔.為了防止不明确的映射,每個索引可以定義的嵌套字段的數量已被限制為50個。 具體請參閱 

Settings to prevent mappings explosion

原文:

https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html#nested-params