2017-03-15 50 views
0

更容易用一個用例來說明我的問題,所以讓我們從elasticsearch指南中獲得example對嵌套數組中包含的兩個值之間的差異進行過濾/排序(僅使用腳本過濾器和doc值)

這列出了一個產品。每個產品都有含經銷商嵌套數組,出售產品說:

{ 
     ... 

     "product" : { 
      "properties" : { 
       "resellers" : { 
        "type" : "nested", 
        "properties" : { 
         "name" : { "type" : "text" }, 
         "price" : { "type" : "double" } 
        } 
       } 
      } 
     } 
    } 

我會怎麼做,如果在所有可能的下?

  • 過濾所有storeA比storeB便宜的產品。例如爲:product.resellers[name=storeA].price < product.resellers[name=storeB].price
  • 訂購產品通過storeA的價格和商店B

這可能分別需要一個腳本過濾和階濾波器,但不知道我怎麼會去這之間的差異。而且,這些類型的查詢經常使用,因此性能很重要。因此,我可能需要堅持docValues而不是訴諸於_source。這可能嗎?

回答

1

是的,這是絕對有可能,你可以做這樣的:

{ 
    "sort": { 
    "_script": { 
     "type": "number", 
     "script": { 
     "inline": "def store1 = _source.resellers.find{it.name == store1}; def store2 = _source.resellers.find{it.name == store2}; (store1 != null && store2 != null) ? store1.price - store2.price : 0", 
     "lang": "groovy", 
     "params": { 
      "store1": "storeA", 
      "store2": "storeB" 
     } 
     }, 
     "order": "asc" 
    } 
    }, 
    "query": { 
    "bool": { 
     "filter": [ 
     { 
      "script": { 
      "script": { 
       "inline": "def store1 = _source.resellers.find{it.name == store1}; def store2 = _source.resellers.find{it.name == store2}; (store1 != null && store2 != null) ? store1.price < store2.price : false", 
       "lang": "groovy", 
       "params": { 
       "store1": "storeA", 
       "store2": "storeB" 
       } 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

排序腳本是這樣的:

def store1 = _source.resellers.find{it.name == store1}; 
def store2 = _source.resellers.find{it.name == store2}; 
(store1 != null && store2 != null) ? store1.price - store2.price : 0 

過濾器腳本有點相似,看起來是這樣的:

def store1 = _source.resellers.find{it.name == store1}; 
def store2 = _source.resellers.find{it.name == store2}; 
(store1 != null && store2 != null) ? store1.price < store2.price : false 

這兩個腳本在輸入中都帶有兩個參數,即經銷商的名稱將您w螞蟻來比較。

UPDATE

不知怎的,我忘了解釋爲什麼它不可能與DOC值做到這一點。 Doc值實際上是倒排索引的倒數,即每個文檔都被映射爲該文檔內存在的令牌。這再加上嵌套的文件保存爲獨立的(但隱藏)在索引文件的事實,像下面

{ 
    "id": 1, 
    "product": "Water", 
    "resellers": [ 
    { 
     "name": "storeA", 
     "price": 20 
    }, 
    { 
     "name": "storeB", 
     "price": 30 
    } 
    ] 
} 

的一個文檔的DOC值應該是這樣的:

Document  | Values 
----------------+--------------------------- 
1 (top-level) | water 
1a (1st nested} | storea, 20 
1b (2nd nested} | storeb, 30 

查看上面的表格,並且由於腳本是在每個文檔的上下文中執行的(無論是頂層還是嵌套),顯而易見的是,當訪問腳本中的doc值時只會生成該文檔的值,因此它無法將它們與另一個文檔中的值進行比較。

訪問源代碼時,我們有效地遍歷了resellers數組,因此可以比較它們之間的值並生成在您的上下文中很有用的東西。

+0

在此操作。同意這將工作,但根據原始問題,我正在尋找一種涉及doc值的解決方案,而不是使用'_source',因爲使用'_source'需要(相當於)全表掃描,這對於我的目的來說太慢。如果這是不可能的,那麼我會很好地解釋爲什麼不這樣做。謝謝 –

+1

你是對的,我忘記了包括爲什麼不能用doc值來做到這一點。 – Val

0

這看起來像一個市場問題。所以我會根據產品的主產品編號分開產品 - 因此產品可以有不同的描述,產品等等,並將它們添加到排序和過濾的優先級。

{ 
     ... 

     "product" : { 
      "properties" : { 
       "masterProduct" : "int", 
       "priority" : "int", 
       "resellers" : { 

        "type" : "nested", 
        "properties" : { 
         "name" : { "type" : "text" }, 
         "price" : { "type" : "double" } 
        } 
       } 
      } 
     } 
    } 

讓我來解釋一下, 首先,

product.resellers [名稱= storeA]。價格< roduct.resellers [名稱= storeB]。價格

我猜的,因爲你提的這個問題要顯示在最便宜的產品搜索結果。所以我認爲在索引產品時,您應該擁有所有經銷商的價格。

如果您知道索引編制時最便宜的優先級,那麼它的優先級爲1,並將其他產品與-1相乘,以便您可以將產品詳細信息以低成本進行分類。 這解決了第二個問題(以storeA的價格和商店B之間的差異來訂購產品)。

畢竟你在索引中獲得了積極的優先級和負面的優先級。所有你可以按優先順序製作過濾器> 0返回最便宜的產品。因此,如果任何經銷商希望成爲搜索結果的頂部或者宣傳自己,則優先考慮優先選擇

+0

這不是一個「市場」問題。我需要將任意商店與其他商店進行比較來填充統計信息顯示板。但是,如果它是,你的將是一個相當優雅的解決方案。 –

相關問題