弹性查询过滤器挑战

时间:2017-03-10 21:13:54

标签: elasticsearch bigdata

我有以下查询,为给定供应商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] 用户John应该只根据产品[A,C,E]查看结果 我将如何编写查询来执行此操作?是否像在bool中的过滤器后添加一个should子句一样简单?

提前致谢!

1 个答案:

答案 0 :(得分: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