2017-03-10 94 views
3

我有以下查詢,針對給定的供應商ID生成排名前100的賣家,針對在product_skus的索引中查找給定供應商的產品skus的銷售指數運行。這很好。彈性查詢篩選器挑戰

query = { 
    size: 0, 
    query: { 
    bool: { 
     filter: [ 
     { 
      constant_score: { 
      filter: { 
       terms: { 
       sku: { 
        index: "product_skus", 
        type: "product", 
        id: supplier_id, 
        path: "skus" 
       } 
       } 
      } 
      } 
     } 
     ], 
     must_not: [] 
    } 
    }, 
    aggs: { 
    unit_sum: { 
     terms: { 
     field: "sku", 
     size: 100, 
     order: { 
      one: "desc" 
     } 
     }, 
     aggs: { 
     one: { 
      sum: { 
      field: "units" 
      } 
     } 
     } 
    } 
    } 
} 

現在我有一個場景,一個給定的用戶需要限制他們的訪問權限的供應商skus的子集。我正在努力解決這個問題的最佳方法。我傾向於有一個用戶可以訪問並進行第二次查找的Skus的另一個索引,但我無法完全理解查詢邏輯。

舉個簡單的例子,如果在上面的查詢中,對於供應商1,我們返回產品[A,B,C,D,E] ,並且用戶約翰應該只看到基於產品的結果[A,C,E] 如何去寫查詢做到這一點?是否像在bool中的過濾器之後添加should子句一樣簡單?

在此先感謝!

+0

這真的要取決於給定用戶有權訪問的SKU的數量......如果它是一個小數字,我認爲您可以使用額外的SHOULD子句逃脫。如果數以百計,那麼你可能會需要另一種解決方案。 –

+0

是的,它就像成百上千,甚至數千。 – Raoot

+0

你有沒有想過使用路由? https://www.elastic.co/blog/customizing-your-document-routing – Adonis

回答

0

路由可能是您在這種情況下需要的,因爲您的場景允許您爲用戶使用路由。作爲將數據組織到單獨的分片中的額外好處,它將允許在查詢中使用路由時提高性能。爲什麼?因爲在使用路由時,請求將僅發送到包含相關數據的分片,而不是跨集羣的每個節點。

你的情況會是什麼樣子?讓我們用一個簡單的映射一看,這應該只有一個ID 123訪問的產品:

product_skus的映射(根據需要修改):

PUT product_skus 
{ 
    "settings": { 
    "index": { 
     "number_of_shards": "5", 
     "number_of_replicas": "1" 
    } 

    }, 
    "mappings": { 
    "product": { 
     "_routing": { 
     "required": true 
     }, 
     "properties": { 
     "supplierId":{ 
      "type": "integer" 
     }, "path":{ 
      "type": "string" 
     } 
     } 
    } 
    } 
} 

現在,讓我們把一個產品在指數型(注意路由):

POST product_skus/product?routing=123 
{ 
    "supplierId": 123, 
    "path": "some/path" 
} 

最後兩個請求,並使用路由它們的輸出:

GET product_skus/_search?routing=123 
{ 
    "query": { 
    "match_all": {} 
    } 
} 

輸出:

{ 
    "took": 4, 
    "timed_out": false, 
    "_shards": { 
    "total": 1, 
    "successful": 1, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 1, 
    "max_score": 1, 
    "hits": [ 
     { 
     "_index": "product_skus", 
     "_type": "product", 
     "_id": "AVrMHzgx28yun46LEMYm", 
     "_score": 1, 
     "_routing": "123", 
     "_source": { 
      "supplierId": 123, 
      "path": "some/path" 
     } 
     } 
    ] 
    } 
} 

第二個查詢:

GET product_skus/_search?routing=124 
{ 
    "query": { 
    "match_all": {} 
    } 
} 

輸出:

{ 
    "took": 1, 
    "timed_out": false, 
    "_shards": { 
    "total": 1, 
    "successful": 1, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 0, 
    "max_score": null, 
    "hits": [] 
    } 
} 

它只是一個簡單的例子,你可能要檢查文檔的詳細信息:

此外,下列顯示只有一個碎片被用於與路由:

GET product_skus/_search_shards?routing=123 

輸出:

{ 
    "nodes": { 
    "1sMKtN6aQ9yyOsTjknWyQA": { 
     "name": "1sMKtN6", 
     "ephemeral_id": "X-V2QGTwTmqUFQb1B6KIUw", 
     "transport_address": "127.0.0.1:9300", 
     "attributes": {} 
    } 
    }, 
    "shards": [ 
    [ 
     { 
     "state": "STARTED", 
     "primary": true, 
     "node": "1sMKtN6aQ9yyOsTjknWyQA", 
     "relocating_node": null, 
     "shard": 0, 
     "index": "product_skus", 
     "allocation_id": { 
      "id": "1MMkFaALRxm1N-x8J8AGhg" 
     } 
     } 
    ] 
    ] 
} 

更多見search shards API細節。