[英]Elasticsearch - Filter where (one of nested array) and (all of nested array)
TL; DR -我該如何檢查是否嵌套數組全的 一個,並符合規定的標准是什么?
我有一份document
。 每個document
都有一個嵌套的outer
對象數組,這些outer
對象本身具有嵌套inner
對象的列表。 我需要對文檔的outer
嵌套對象中至少有一個匹配的所有文檔執行過濾。 當我說匹配時,我的意思是所有 outer
嵌套對象的inner
對象都以某種方式匹配。 這是一個示例映射供參考;
{ "document" : {
"properties" : {
"name" : {
"type" : "string"
},
"outer" : {
"type" : "nested",
"properties" : {
"inner" : {
"type" : "nested",
"properties" : {
"match" : {
"type" : "string",
"index" : "not_analyzed"
},
"type" : {
"type" : "string",
"index" : "not_analyzed"
}
}}}}}}
}
如果文檔沒有outer
/ inner
對象,則認為它匹配。 但是為了使事情變得更糟,需要根據一種條件邏輯方式(例如SQL中的CASE
)的type
來考慮內部對象的不同匹配。 例如,如果type
是術語"Country"
那么如果match
是指定的國家代碼(例如ES
則認為inner
對象匹配。 文檔可能具有不同type
inner
對象,並且不保證將存在特定類型。
來自命令式(Java)編程背景我在弄清楚如何實現這種過濾方面遇到了令人難以置信的麻煩。 沒有什么我能想到甚至模糊地匹配這種行為。 到目前為止,我所擁有的只是過濾后的查詢;
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"bool" : {
"should" : {
"missing" : {
"field" : "outer.inner.type"
}
}}}}
}
所以,問題是......
如何才能篩選到誰擁有至少一個文件outer
,其擁有的所有物體inner
匹配基於對象type
的inner
對象?
進一步詳情按要求 -
{
"name":"First",
"outer":[
{
"inner":[
{"match":"ES","type":"Country"},
{"match":"Elite","type":"Market"}
]
},{
"inner":[
{"match":"GBR","type":"Country"},
{"match":"1st Class","type":"Market"},
{"match":"Admin","type":"Role"}
]
}
],
"lockVersion":0,"sourceId":"1"
}
如果我們要提供"1st Class"
市場和國家"GRB"
,上面的例子應該通過過濾器,因為兩個outer
對象中的第二個將被認為是匹配,因為兩個inner
對象匹配。 但是,如果我們提供了國家/地區"GRB"
和市場"Elite"
那么我們就不會返回此文檔,因為兩個outer
對象都不會打擾它們的inner
對象完全匹配。 如果我們想要匹配第二個outer
對象,那么所有三個inner
都需要匹配。 請注意,第三個inner
有一個額外的type
。 這導致如果存在類型然后它需要匹配它的情況, 否則它不需要匹配,因為它不存在。
使一個符合某些標准的嵌套數組變得非常簡單。 如果任何嵌套對象數組與指定的內部過濾器匹配,則嵌套過濾器的計算結果為匹配/ true。 例如,給定一個outer
對象數組,其中一個對象的字段match
值"matching"
則以下內容將被視為true。
"nested": {
"path": "outer",
"filter": {
"term" : { "match" : "matching" }
}
}
如果其中一個嵌套outer
對象具有名為match
的字段且值為"matching"
,則上述內容將被視為true / matching。
如果數組中的所有嵌套對象匹配更有趣,則僅將嵌套過濾器視為匹配。 事實上,這是不可能的。 但是,如果只有一個嵌套對象與過濾器匹配,則認為它是匹配的,我們可以反轉邏輯並說“如果沒有嵌套對象不匹配”來實現我們需要的東西。 例如,給定的嵌套的陣列outer.inner
對象,其中所有這些對象的具有場match
具有值"matching"
以下將被認為是正確的。
"not" : {
"nested": {
"path": "outer.inner",
"filter": {
"not" : {
"term" : { "match" : "matching" }
}
}
}
}
以上將被認為是真/匹配,因為沒有嵌套的outer.inner
對象沒有 (雙負)有一個名為match
的字段,其值為"matching"
。 這當然是相同的所有嵌套的 inner
具有字段對象match
具有值"matching"
。
您無法使用傳統的缺失過濾器檢查是否缺少包含嵌套對象的字段。 這是因為,嵌套的對象實際上並沒有在文檔中可言,它們存儲在別處。 因為這樣的缺失過濾器將始終被視為真實。 但是你可以做的是檢查match_all
過濾器是否返回沒有這樣的結果;
"not": {
"nested": {
"path": "outer",
"filter": {
"match_all": {}
}
}
}
如果match_all
找不到結果,則認為這是真/匹配。
嗯,這是一個doozy,但這個查詢似乎做你想要的:
POST /test_index/_search
{
"query": {
"filtered": {
"filter": {
"nested": {
"path": "outer",
"filter": {
"bool": {
"must": [
{
"nested": {
"path": "outer.inner",
"filter": {
"bool": {
"must": [
{ "term": { "outer.inner.type": "Market" } },
{ "term": { "outer.inner.match": "1st Class" } }
]
}
}
}
},
{
"nested": {
"path": "outer.inner",
"filter": {
"bool": {
"must": [
{ "term": { "outer.inner.type": "Country" } },
{ "term": { "outer.inner.match": "GBR" } }
]
}
}
}
}
]
}
}
}
}
}
}
}
這是我用來測試它的一些代碼:
http://sense.qbox.io/gist/f554c2ad2ef2c7e6f5b94b1ddb907813370f4edc
如果您需要對邏輯進行一些解釋,請告訴我。 它有點牽扯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.