這是ElasticSearch 2.4 版本系列的第六篇:html
在ElasticSearch中,使用JSON結構來存儲數據,一個Key/Value對是JSON的一個字段,而Value能夠是基礎數據類型,也能夠是數組,文檔(也叫對象),或文檔數組,所以,每一個JSON文檔都內在地具備層次結構。複合數據類型是指數組類型,對象類型和嵌套類型,各個類型的特色分別是:正則表達式
一,對象類型數組
JSON文檔是有層次結構的,一個文檔可能包含其餘文檔,若是一個文檔包含其餘文檔,那麼該文檔值是對象類型,其數據類型是對象,ElasticSearch默認把文檔的屬性type設置爲object,即"type":"object"。數據結構
例如,在建立索引映時,定義name字段爲對象類型,不須要顯式定義type屬性值,其默認值是object:app
"manager":{ "properties":{ "age":{ "type":"integer"}, "name":{ "properties":{ "first":{"type":"string"}, "last":{ "type":"string"} } } } }
默認狀況下,上述文檔類型被索引爲以點號命名的數據結構,把層次結構展開以後,數據結構是由扁平的key/value對構成:elasticsearch
{ "manager.age": 30, "manager.name.first": "John", "manager.name.last": "Smith" }
二,開箱即用的數組類型ide
在ElasticSearch中,沒有專門的數組(Array)數據類型,可是,在默認狀況下,任意一個字段均可以包含0或多個值,這意味着每一個字段默認都是數組類型,只不過,數組類型的各個元素值的數據類型必須相同。在ElasticSearch中,數組是開箱即用的(out of box),不須要進行任何配置,就能夠直接使用。post
1,數組類型ui
在同一個數組中,數組元素的數據類型是相同的,ElasticSearch不支持元素爲多個數據類型:[ 10, "some string" ],經常使用的數組類型是:url
對於文檔數組,每一個元素都是結構相同的文檔,文檔之間都不是獨立的,在文檔數組中,不能獨立於其餘文檔而去查詢單個文檔,這是由於,一個文檔的內部字段之間的關聯被移除,各個文檔共同構成對象數組。
對整數數組進行查詢,例如,使用多詞條(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,必須賦值的參數:
2,使用嵌套查詢訪問嵌套文檔
GET my_index/_search { "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "White" }} ] } } } } }
五,使用C#索引數組類型
1,建立ElasticSearch的索引映射
{ "settings":{ "number_of_shards":5, "number_of_replicas":0 }, "mappings":{ "events":{ "dynamic":"false", "properties":{ "eventid":{ "type":"long", "store":true, "index":"not_analyzed" }, "eventname":{ "type":"string", "store":true, "index":"analyzed", "fields":{ "raw":{ "type":"string", "store":true, "index":"not_analyzed" } } }, "topics":{ "type":"integer", "store":true, "index":"analyzed" } } } } }
對於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 List List<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