elasticsearch按嵌套文档的总和筛选

rjee0c15  于 2021-06-10  发布在  ElasticSearch
关注(0)|答案(1)|浏览(427)

我尝试过滤嵌套过滤对象中的属性总和在某个范围内的产品。
我有以下Map:

{
  "product": {
    "properties": {
      "warehouses": {
        "type": "nested",
        "properties": {
          "stock_level": {
            "type": "integer"
          }
        }
      }
    }
  }
}

示例数据:

{
  "id": 1,
  "warehouses": [
    {
      "id": 2001,
      "stock_level": 5
    },
    {
      "id": 2002,
      "stock_level": 0
    },
    {
      "id": 2003,
      "stock_level": 2
    }
  ]
}

在elasticsearch 5.6中,我经常这样做:

GET products/_search
{
  "query": {
    "bool": {
      "filter": [
        [
          {
            "script": {
              "script": {
                "source": """
int total = 0;
for (def warehouse: params['_source']['warehouses']) {
  if (params.warehouse_ids == null || params.warehouse_ids.contains(warehouse.id)) {
    total += warehouse.stock_level;
  }
}
boolean gte = true;
boolean lte = true;
if (params.gte != null) {
  gte = (total >= params.gte);
}
if (params.lte != null) {
  lte = (total <= params.lte);
}
return (gte && lte);

""",
                "lang": "painless",
                "params": {
                  "gte": 4
                }
              }
            }
          }
        ]
      ]
    }
  }
}

问题是 params['_source']['warehouses'] 在es6.8中不再工作,我无法找到访问脚本中嵌套文档的方法。
我试过: doc['warehouses'] -返回错误(“在类型为[]的Map中找不到[warehouses]的字段”) ctx._source.warehouses -“变量[ctx]未定义。”
我也尝试过使用脚本字段,但似乎脚本字段是在最后一个阶段计算出来的,在查询期间不可用。
我还有一个按相同逻辑排序的方法(按给定仓库中的库存总和对产品进行排序),它就像一个符咒:

"sort": {
    "warehouses.stock_level": {
      "order": "desc",
      "mode": "sum",
      "nested": {
        "path": "warehouses"
        "filter": {
           "terms": {
             "warehouses.id": [2001, 2003]
           }
        }
      }
    }
  }

但我也找不到访问此排序值的方法:(
有什么办法能做到这一点吗?谢谢。

w8ntj3qf

w8ntj3qf1#

我最近也有同样的问题。结果发现,这个变化发生在6.4版本的某个地方,在重构和访问过程中 _source 是非常气馁的,看起来人们仍在使用/想要使用它。
下面是一个利用 include_in_root 参数。
调整Map

PUT product
{
  "mappings": {
    "properties": {
      "warehouses": {
        "type": "nested",
        "include_in_root": true,     <--
        "properties": {
          "stock_level": {
            "type": "integer"
          }
        }
      }
    }
  }
}

删除并重新索引
在访问展平值时,在for循环中重建各个仓库项目:

GET product/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "script": {
            "script": {
              "source": """
                  int total = 0;

                  def ids = doc['warehouses.id'];
                  def levels = doc['warehouses.stock_level'];

                  for (def i = 0; i <  ids.length; i++) {
                    def warehouse = ['id':ids[i], 'stock_level':levels[i]];

                    if (params.warehouse_ids == null || params.warehouse_ids.contains(warehouse.id)) {
                      total += warehouse.stock_level;
                    }
                  }

                  boolean gte = true;
                  boolean lte = true;
                  if (params.gte != null) {
                    gte = (total >= params.gte);
                  }
                  if (params.lte != null) {
                    lte = (total <= params.lte);
                  }
                  return (gte && lte);
              """,
              "lang": "painless",
              "params": {
                  "gte": 4
              }
            }
          }
        }
      ]
    }
  }
}

请注意,此方法假定所有仓库都包含非空id和库存级别。

相关问题