2016-08-23 172 views
2

最近我開始使用ElasticSearch,我打算堅持使用它來獲得我正在構建的服務。elasticsearch中的聚合和排序

我基本上有以下幾種類型:

  • 搜索
  • 提供報價

每個搜索的

  • 價格都有一套信息加上SID(搜索ID),每個優惠都有一個OID(優惠ID)加上搜索的SID和一組價格。

    我會異步接收數據,以避免使用_update,而不是在報價中包含價格數組並更新它,每個價格都存儲在一個單獨的文檔中,幷包含搜索ID,商品ID和價格本身。

    我向:

    • 過濾器由SID
    • 骨料由OID
    • 按價格排序骨料

    我怎麼能做到這一點?任何提示?我在閱讀文檔瞭解如何聚集,但我完全不知道該:(

    編輯:

    在這裏有一個例子集

    搜索(UUID是SID)

    { 
        'sid_1': { 'q': 'bread', 'sid': 'sid_1' }, 
        'sid_2': { 'q': 'milk', 'sid': 'sid_2' }, 
        'sid_3': { 'q': 'donuts', 'sid': 'sid_3' } 
    } 
    

    優惠(UUID是SID#OID)

    { 
        'sid_1#kamut-bread': { 'name': 'kamut bread', 'sid': 'sid_1', 'oid': 'kamut-bread' }, 
        'sid_1#chocolate-bread': { 'name': 'chocolate bread', 'sid': 'sid_1', 'oid': 'chocolate-bread' }, 
        'sid_1#plastic-bread': { 'name': 'plastic bread', 'sid': 'sid_1', 'oid': 'plastic-bread' }, 
        'sid_2#soya-milk': { 'name': 'soya milk', 'sid': 'sid_2', 'oid': 'soya-milk' }, 
        'sid_2#vaccine-milk': { 'name': 'vaccine milk', 'sid': 'sid_2', 'oid': 'vaccine-milk' }, 
        'sid_2#milk': { 'name': 'milk', 'sid': 'sid_2', 'oid': 'milk' }, 
        'sid_3#cream-donuts': { 'name': 'cream donuts', 'sid': 'sid_3', 'oid': 'cream-donuts' }, 
        'sid_3#chocolate-donuts': { 'name': 'chocolate donuts', 'sid': 'sid_3', 'oid': 'chocolate-donuts' }, 
        'sid_3#square-donuts': { 'name': 'square donuts', 'sid': 'sid_3', 'oid': 'square-donuts' } 
    } 
    

    OFFERS_PRICES(UUID是SID#OID#合夥人)

    { 
        'sid_1#kamut-bread#amazon': { 'partner': 'amazon', 'sid': 'sid_1', 'oid': 'kamut-bread', 'price': 10.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#kamut-bread#store2': { 'partner': 'store2', 'sid': 'sid_1', 'oid': 'kamut-bread', 'price': 11.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#kamut-bread#store3': { 'partner': 'store3', 'sid': 'sid_1', 'oid': 'kamut-bread', 'price': 10.4, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#kamut-bread#store4': { 'partner': 'store4', 'sid': 'sid_1', 'oid': 'kamut-bread', 'price': 10.8, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#chocolate-bread#amazon': { 'partner': 'amazon', 'sid': 'sid_1', 'oid': 'chocolate-bread', 'price': 7.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#chocolate-bread#store2': { 'partner': 'store2', 'sid': 'sid_1', 'oid': 'chocolate-bread', 'price': 7.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#chocolate-bread#store3': { 'partner': 'store3', 'sid': 'sid_1', 'oid': 'chocolate-bread', 'price': 8.4, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#chocolate-bread#store4': { 'partner': 'store4', 'sid': 'sid_1', 'oid': 'chocolate-bread', 'price': 9.8, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#plastic-bread#amazon': { 'partner': 'amazon', 'sid': 'sid_1', 'oid': 'plastic-bread', 'price': 70.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#plastic-bread#store2': { 'partner': 'store2', 'sid': 'sid_1', 'oid': 'plastic-bread', 'price': 75.1, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#plastic-bread#store3': { 'partner': 'store3', 'sid': 'sid_1', 'oid': 'plastic-bread', 'price': 88.4, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } }, 
        'sid_1#plastic-bread#store4': { 'partner': 'store4', 'sid': 'sid_1', 'oid': 'plastic-bread', 'price': 97.8, 'fees': { 'mastercard': 1, 'visa': 1, 'paypal': 2, 'wiretransfer': 0 } } 
        ... 
    } 
    

    由於性能原因代碼將無法彙總數據,而是將分別返回它們(搜索,報價和優惠的價格)和前端將它們聚合起來,將允許我(幾乎)直接從彈性流式傳輸數據,而不必預先詳細說明它們。

    提取搜索和報價後,我想:

    • 由OID
    • 提取的價格爲SID sid_1
    • 到組的價格由價格彙總排序(或按價格+特定費用,但我可以用groovy處理這個問題)
  • +1

    可否請你用一個更具體的樣本延長你的問題上的數據看起來像以及您想要執行哪種查詢和聚合?你想達到什麼目標? –

    回答

    1

    我發現了聚合類型scripted_metric的存在,並且在玩之後我想出了這個查詢

    { 
        "size": 0, 
        "query" : { 
         "match_all" : {} 
        }, 
    
        "aggs": { 
         "offer_prices": { 
          "scripted_metric": { 
           "init_script" : "_agg[\"offers_prices\"] = [:].withDefault{[:]}", 
    
           "map_script" : "def parent = doc._parent.value; def partner = doc.partner.value; def price = doc.price.value; if (!_agg.offers_prices.containsKey(parent)) { _agg.offers_prices[parent] = [ parent: parent, sid: doc.sid.value, oid: doc.oid.value, bestPrice: Double.MAX_VALUE, bestPartner: null, partners: [:] ]; }; _agg.offers_prices[parent].partners[partner] = [ \"partner\": partner, \"price\": price, \"ccfees\": _source.ccfees ]; if (_agg.offers_prices[parent].bestPrice > price) { _agg.offers_prices[parent].bestPrice = price; _agg.offers_prices[parent].bestPartner = partner; }", 
    
           "combine_script" : "return _agg.offers_prices;", 
    
           "reduce_script" : "def offers_prices_all = [:]; _aggs.each { offers_prices_per_shard -> offers_prices_per_shard.each { oid, offers_prices -> offers_prices_all[oid] = offers_prices}; }; offers_prices_all = offers_prices_all.sort { a, b -> a.value.bestPrice <=> b.value.bestPrice }; return offers_prices_all;" 
    
          } 
         } 
        } 
    } 
    

    這不是最終版本,我必須做一些修正,我要測試性能,但它似乎是一個可能的解決方案:使用_parent

    • 查詢組數據計算TE最佳價格聚集的
    • 排序聚合由最佳價格

    靜止TODO:

    • 排序聚集的最佳價格+費用
    • 按價格排序單聚集的合作伙伴名單
    • 測試的性能和資源消耗

    注:

    • 我已經添加了_parent映射,並且我正在使用文檔的_parent屬性來分組數據,但可以手動進行保佑它串聯SID和OID
    • 腳本是使用屬性ccfees,但在這個例子中數據集我張貼時則稱爲費
  • +0

    幹得好,夥計! –