Elasticsearch入門 第六篇:複合資料型別——數組,對象和嵌套,

來源:互聯網
上載者:User

Elasticsearch入門 第六篇:複合資料型別——數組,對象和嵌套,

在Elasticsearch中,使用JSON結構來儲存資料,一個Key/Value對是JSON的一個欄位,而Value可以是基礎資料類型,也可以是數組,文檔(也叫對象),或文檔數組,因此,每個JSON文檔都內在地具有階層。複合資料型別是指數群組類型,物件類型和巢狀型別,各個類型的特點分別是:

  • 數組欄位是指一個欄位有多個值,每個值都是該數組欄位的一個元素;元素的類型可以是基礎類型,也可以是文件類型;
  • 物件類型是指欄位的值是一個JSON文檔;
  • 嵌套欄位是指物件類型的一個特殊版本,Elasticsearch引擎在內部把嵌套欄位索引成單個文檔。如果在嵌套欄位中定義對象數組,那麼對象數組中的每個元素(文檔)都被索引成單個文檔,每個文檔都能被獨立地查詢。

一,物件類型

JSON文檔是有階層的,一個文檔可能包含其他文檔,如果一個文檔包含其他文檔,那麼該文檔值是物件類型,其資料類型是對象,Elasticsearch預設把文檔的屬性type設定為object,即"type":"object"。

例如,在建立索引映時,定義name欄位為物件類型,不需要顯式定義type屬性值,其預設值是object:

"manager":{     "properties":{        "age":{ "type":"integer"},      "name":{           "properties":{              "first":{"type":"string"},            "last":{ "type":"string"}         }      }   }}

預設情況下,上述文件類型被索引為以點號命名的資料結構,把階層展開之後,資料結構是由扁平的key/value對構成:

{  "manager.age":        30,  "manager.name.first": "John",  "manager.name.last":  "Smith"}

二,開箱即用的數群組類型

在Elasticsearch中,沒有專門的數組(Array)資料類型,但是,在預設情況下,任意一個欄位都可以包含0或多個值,這意味著每個欄位預設都是數群組類型,只不過,數群組類型的各個元素值的資料類型必須相同。在Elasticsearch中,數組是開箱即用的(out of box),不需要進行任何配置,就可以直接使用。

1,數群組類型

在同一個數組中,數組元素的資料類型是相同的,Elasticsearch不支援元素為多個資料類型:[ 10, "some string" ],常用的數群組類型是:

  • 字元數組: [ "one", "two" ]
  • 整數數組: productid:[ 1, 2 ]
  • 對象(文檔)數組: "user":[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }],Elasticsearch內部把對象數組展開為 {"user.name": ["Mary", "John"], "user.age": [12,10]}

對於文檔數組,每個元素都是結構相同的文檔,文檔之間都不是獨立的,在文檔數組中,不能獨立於其他文檔而去查詢單個文檔,這是因為,一個文檔的內部欄位之間的關聯被移除,各個文檔共同構成對象數組。

對整數數組進行查詢,例如,使用多詞條(terms)查詢類型,查詢productid為1和2的文檔:

{     "query":{        "terms":{           "productid":[ 1, 2 ]      }   }}

2,對象數組

通過PUT動詞,自動建立索引和文件類型,在文檔中建立對象數組:

PUT my_index/my_type/1{  "group" : "fans",  "user" : [     {      "first" : "John",      "last" :  "Smith"    },    {      "first" : "Alice",      "last" :  "White"    }  ]}

Elasticsearch引擎內部把對象數組展開成扁平的資料結構,把上例的文件類型的資料結構展開之後,文檔資料類似於:

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

欄位 user.first 和 user.last 被展開成數組欄位,但是,這樣展開之後,單個文檔內部的欄位之間的關聯就會丟失,在該例中,展開的文檔資料丟失first和last欄位之間的關聯,比如,Alice 和 white 的關聯就丟失了。

三,嵌套資料類型

嵌套資料類型是對象資料類型的特殊版本,它允許對象數組中的各個對象被索引,數組中的各個對象之間保持獨立,能夠對每一個文檔進行單獨查詢,這就意味著,嵌套資料類型保留文檔的內部之間的關聯,Elasticsearch引擎內部使用不同的方式處理嵌套資料類型和對象數組的方式,對於嵌套資料類型,Elasticsearch把數組中的每一個嵌套文檔(Nested Document)索引為單個文檔,這些文檔是隱藏(Hidden)的,文檔之間是相互獨立的,但是,保留文檔的內部欄位之間的關聯,使用巢狀查詢(Nested Query)能夠獨立於其他文檔而去查詢單個文檔。在建立嵌套資料類型的欄位時,需要設定欄位的type屬性為nested。

1,在索引映射中建立嵌套欄位

設定user欄位為嵌套資料類型,由於每個欄位預設都可以是數群組類型,因此,嵌套欄位也可以是對象數組。

"mappings":{     "my_type":{        "properties":{           "group":{ "type":"string"},         "user":{              "type":"nested",            "properties":{                 "first":{ "type":"string"},               "second":{  "type":"string"}            }         }      }   }}

2,為嵌套欄位賦值

為嵌套欄位賦予多個值,那麼Elasticsearch自動把欄位值轉換為數群組類型。

PUT my_index/my_type/1{  "group" : "fans",  "user" : [     { "first" : "John", "last" :  "Smith"},    { "first" : "Alice", "last" :  "White"}  ]}

在Elasticsearch內部,嵌套的文檔(Nested Documents)被索引為很多獨立的隱藏文檔(separate documents),這些隱藏文檔只能通過巢狀查詢(Nested Query)訪問。每一個嵌套的文檔都是嵌套欄位(文檔數組)的一個元素。嵌套文檔的內部欄位之間的關聯被Elasticsearch引擎保留,而嵌套文檔之間是相互獨立的。在該例中,Elasticsearch引起保留Alice和White之間的關聯,而John和White之間是沒有任何關聯的。

預設情況下,每個索引最多建立50個嵌套文檔,可以通過索引設定選項:index.mapping.nested_fields.limit 修改預設的限制。

Indexing a document with 100 nested fields actually indexes 101 documents as each nested document is indexed as a separate document.

四,巢狀查詢

巢狀查詢用於查詢嵌套對象,執行巢狀查詢執行的條件是:嵌套對象被索引為單個文檔,查詢作用在根文檔(Root Parent)上。巢狀查詢由關鍵字“nested”指定:

"nested" : {        "path" : "obj1",        "query" : {...}

1,必須賦值的參數:

  • path參數:指定嵌套欄位的文檔路徑,根路徑是頂層的文檔,通過點號“.”來指定嵌套文檔的路徑;
  • query參數:在匹配路徑(參數path)的嵌套文檔上執行查詢,query參數指定對嵌套文檔執行的查詢條件。

2,使用巢狀查詢訪問嵌套文檔

GET my_index/_search{  "query": {    "nested": {      "path": "user",      "query": {        "bool": {          "must": [            { "match": { "user.first": "Alice" }},            { "match": { "user.last":  "White" }}           ]        }      }    }  }}

五,使用C#索引數群組類型

1,建立Elasticsearch的索引映射

View Code

對於topics欄位,類型是integer,賦予其一組整數值[1,2,3],那麼該欄位就能儲存數組。

"topics":{      "type":"integer",    "store":true,    "index":"analyzed"}

2,建立資料模型(Data Model)

為數組欄位定義為List類型,每個清單項目的資料類型是int。

public class EventBase{    public long eventid { get; set; }}public class EbrieEvents:EventBase{    public string eventname { get; set; }    public List<int> topics { get; set; }}

3,為欄位賦值

為List欄位topics賦值,調用NEST對該文檔進行索引

EbrieEvents pb = new EbrieEvents();//Topics ListList<string> strTopics = TableRow["Topics"].ToString().TrimEnd(',').Split(',').ToList();List<int> topics = new List<int>();foreach(string str in strTopics){    topics.Add(int.Parse(str));}pb.topics = topics;  

4,查詢數組欄位

{     "query":{        "terms":{           "topics":[1001,487]      }   }}

 

參考文檔:

Elasticsearch Reference [2.4] » Mapping » Field datatypes

Elasticsearch Reference [2.4] » Query DSL » Joining queries » Nested Query

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.