Elastic Search按嵌套文档的数量过滤

发布于 2021-02-01 11:54:53

我有一个针对 公司 的elasticsearch索引,该索引具有一个称为 事务 的嵌套对象。交易至少有一个 日期 字段。这是一个示例:

firms: [
  {
    "name": "abc",
    "address" : "xyz",
    "transactions": [
       {
         "date" : "2014-12-20"
         "side" : "buyer"
       },
       ...
     ]
  },
  ...
]

有了这些数据,我想查询过去6或12个月内所有(例如)交易超过3次的公司。

以下查询返回在过去12个月中至少有一笔交易的公司:

POST firms/firm/_search
    {
    "query": {
        "nested": {
           "path": "transactions",
           "query": {
               "bool": {
                   "must": [
                      {
                          "match": {
                             "transactions.side": "buyer"
                          }
                      },
                      {
                          "range": {
                             "transactions.date": {
                                "from": "2014-10-24",
                                "to": "2015-10-24"
                             }
                          }
                      }
                   ]
               }
           }
        }  
    }
}

我不确定如何扩展此查询以匹配在y +个月内进行x +交易的公司。任何帮助将不胜感激。谢谢

关注者
0
被浏览
247
1 个回答
  • 面试哥
    面试哥 2021-02-01
    为面试而生,有面试问题,就找面试哥。

    除了使用,我认为您别无选择script。像这样:

    {
      "query": {
        "bool": {
          "must": [
            {
              "nested": {
                "path": "transactions",
                "query": {
                  "bool": {
                    "must": [
                      {
                        "match": {
                          "transactions.side": "buyer"
                        }
                      },
                      {
                        "range": {
                          "transactions.date": {
                            "from": "2014-10-24",
                            "to": "2015-10-24"
                          }
                        }
                      }
                    ]
                  }
                }
              }
            },
            {
              "filtered": {
                "filter": {
                  "script": {
                    "script": "if(_source.transactions.size<3) return false;fromDate=Date.parse('yyyy-MM-dd',fromDateParam);toDate=Date.parse('yyyy-MM-dd',toDateParam);count=0;for(d in _source.transactions){docsDate=Date.parse('yyyy-MM-dd',d.get('date'));if(docsDate>=fromDate && docsDate<=toDate){count++};if(count==3){return true;}};return false;",
                    "params": {
                      "fromDateParam":"2014-10-24",
                      "toDateParam":"2015-10-24"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
    

    range对于没有日期匹配的那些文档,实际的过滤器是“优化”的。因此,此文档(范围内没有日期)将不会到达费用更高的script过滤器。

    script本身首先检查是否交易的数量少于3。如果是这样,请不要打扰所有日期检查并返回false。如果超过,3则取每个日期并与参数进行比较。一旦3达到计数,请停止查看其余日期并返回true



推荐阅读
知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看