Elasticsearch -如何找出嵌套对象的字段值大于X的所有文档,并带有最大日期

mm5n2pyu  于 7个月前  发布在  ElasticSearch
关注(0)|答案(1)|浏览(67)

我有几个文档是针对一个公司模型的。每个公司都有一些财务报表。它们被设计为Elasticsearch的嵌套对象。例如:

[
  {
    "id": 1,
    "financials": [
      {
        "periodEndDate": "2022-06-30",
        "cash": 10000,
        "inventory": 24000
      },
      {
        "periodEndDate": "2022-12-31",
        "cash": 12000,
        "inventory": 19000
      }
    ]
  },
  {
    "id": 2,
    "financials": [
      {
        "periodEndDate": "2022-12-31",
        "cash": 200000,
        "inventory": 1590000
      },
      {
        "periodEndDate": "2023-03-31",
        "cash": 210000,
        "inventory": 1430000
      }
    ]
  }
]

字符串
我想找出最新期间结束日期报表中现金> 200000的所有公司,因为公司2的最近一份报表是periodEndDate 2023-03-31,而该报表的现金为 210000,所以希望得到的结果是公司2。
如何编写查询?
此外,如果要筛选最近日期之后第二个日期为的报告,该查询是什么?
我找到了这个帖子:ElasticSearch - Get the documents where the value of a field is x and the max date of the type is lower then y date但它需要“负”过滤器,这对我不起作用,因为财务报表嵌套对象的字段太多了。

xdnvmnnf

xdnvmnnf1#

如果公司的数量足够小,你不需要浏览它们,你可以使用top_hitsbucket_selector聚合的组合来完成。基本上,top_hits将找到最新的报告,bucket_selector将删除所有没有足够现金的公司。

PUT test
{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "financials": {
        "type": "nested",
        "properties": {
          "periodEndDate": {
            "type": "date"
          },
          "cash": {
            "type":"long"
          },
          "inventory": {
            "type": "long"
          }
        }
      }
    }
  }
}

POST test/_bulk?refresh
{"index":{"_id":1}}
{"id":1,"financials":[{"periodEndDate":"2022-06-30","cash":10000,"inventory":24000},{"periodEndDate":"2022-12-31","cash":12000,"inventory":19000}]}
{"index":{"_id":2}}
{"id":2,"financials":[{"periodEndDate":"2022-12-31","cash":200000,"inventory":1590000},{"periodEndDate":"2023-03-31","cash":210000,"inventory":1430000}]}

POST test/_search
{
  "size": 0,
  "aggs": {
    "companies": {
      "terms": {
        "field": "id"
      },
      "aggs": {
        "nested": {
          "nested": {
            "path": "financials"
          },
          "aggs": {
            "last_cash": {
              "top_hits": {
                "sort": [
                  {
                    "financials.periodEndDate": {
                      "order": "desc"
                    }
                  }
                ],
                "_source": {
                  "includes": [
                    "financials.cash",
                    "financials.periodEndDate"
                  ]
                },
                "size": 1
              }
            }
          }
        },
        "having.top_cash": {
          "bucket_selector": {
            "buckets_path": {
              "last_cash": "nested>last_cash[_source.cash]"
            },
            "script": "params.last_cash > 200000"
          }
        }
      }
    }
  }
}

字符串
这种方法有几个局限性,包括可扩展性差,它可以处理的公司数量有限,不支持第二个最旧的报告。如果您还需要按相关性对公司进行排序或浏览它们,它也不是最佳解决方案。
为了实现所有这些功能并构建一个可扩展的解决方案,我建议在索引时添加一个额外的处理,并将最新的报告和第二个最新的报告作为主对象中的专用字段进行索引,而不是将它们存储为嵌套并在搜索时尝试查找最新的和第二个最新的报告。因此,基本上您的记录应该如下所示:

{
    "id": 1,
    "latest_finanicals": {
            "periodEndDate": "2022-12-31",
            "cash": 12000,
            "inventory": 19000
        }
    },
    "previous_finanicals": {
            "periodEndDate": "2022-06-30",
            "cash": 10000,
            "inventory": 24000
        }
    }
    "financials": [
      {
        "periodEndDate": "2022-06-30",
        "cash": 10000,
        "inventory": 24000
      },
      {
        "periodEndDate": "2022-12-31",
        "cash": 12000,
        "inventory": 19000
      }
    ]
  }


使用latest_finanicalsprevious_finanicalsobject类型代替nested类型。然后所有查询将变得非常简单。

相关问题