如何根据elasticsearch中的子文档命中进行聚合和排序

时间:2017-01-03 08:06:58

标签: elasticsearch

我的文档索引如下:

{
  "attrib": "value", // etc
  "prices": [
    {
      "p": 10,
      "d": "2016-01-01"
    },
    {
      "p": 20,
      "d": "2016-01-02"
    },
    {
      "p": 30,
      "d": "2016-01-03"
    },
    {
      "p": 40,
      "d": "2016-01-04"
    }
  ]
}

我想得到聚合桶来告诉我这样的事情:

价格桶

  • prices.p介于1到10(20)
  • 之间
  • prices.p介于11和20之间(22)
  • prices.p介于21至30(2)
  • 之间

Date Buckets

  • prices.d 1月1日至1月30日(20日)
  • prices.d 2月1日至2月28日(22日)
  • prices.d 3月1日至3月30日(2)

如果计数显示X和Y之间prices.X的父文档数,则不是总价格数。

除此之外,如果我想执行过滤器以仅获取prices.p介于1到30之间的文档,我需要聚合来反映这一点。

第三,我希望能够通过结果的最高孩子命中我的结果。

所以用简单的英语,我的查询是:

"找到我所有的文件,其中X和Y之间至少有一个价格,日期在A和B之间,按价格(或按要求的日期)订购结果"

到目前为止我的查询:

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "nested": {
                "filter": {
                  "bool": {
                    "must": [
                      {
                        "range": {
                          "prices.p": {
                            "gte": 1,
                            "lte": 30
                          }
                        }
                      }
                    ]
                  }
                },
                "path": "prices",
                "inner_hits": {
                  "sort": [
                    "p"
                  ]
                }
              }
            }
          ]
        }
      },
      "query": {
        "match_all": {}
      }
    }
  }
}

这会以默认排序顺序返回文档,但inner_hitsprices.p排序 - 这样我就可以显示项目的最低价格以及该价格的日期({{1 }})。

同样,我希望能够过滤两个日期之间prices.d的位置 - 同时汇总日期。

最后,我希望能够通过第一个内部点击(prices.dp)订购我的完整文档点击次数

1 个答案:

答案 0 :(得分:1)

您必须使用嵌套聚合。要构建两个存储桶,您必须运行两个并行的嵌套聚合。

为了更好地过滤您的存储桶,您可以添加一个父查询,该查询将过滤您的文档集以及您的存储桶。

以下是查询,为简单起见,我将嵌套的d类型更改为整数,但这也适用于日期范围。

{
  "aggs": {
    "p_range": {
      "nested": {
        "path": "prices"
      },
      "aggs": {
        "p_nested_range": {
          "range": {
            "field": "prices.p",
            "ranges": [
              {
                "from": 0,
                "to": 1000
              },
              {
                "from": 1000,
                "to": 2000
              }
            ]
          }
        }
      }
    },
    "d_range" :{
      "nested": {
        "path": "prices"
      },
      "aggs": {
        "d_nested_range": {
          "range": {
            "field": "prices.d",
            "ranges": [
              {
                "from": 0,
                "to": 500
              },
              {
                "from": 500,
                "to": 1000
              }
            ]
          }
        }
      }
    }
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "nested": {
                "filter": {
                  "bool": {
                    "must": [
                      {
                        "range": {
                          "prices.p": {
                            "gte": 200,
                            "lte": 1400
                          }
                        }
                      }
                    ]
                  }
                },
                "path": "prices",
                "inner_hits": {
                  "sort": [
                    "prices.p"
                  ]
                }
              }
            }
          ]
        }
      },
      "query": {
        "match_all": {}
      }
    }
  }
}

如果您只想过滤文档集,但又不希望您的查询影响您的存储分区,那么您可以查看post_filter

编辑 - 要根据价格嵌套类型中的第一个inner_hit对父文档进行排序,请使用以下查询。 你不需要在innerhits中有一个sort子句,因为内部排序用于排序嵌套类型而不是父文档

{
  "aggs": {
    "p_range": {
      "nested": {
        "path": "prices"
      },
      "aggs": {
        "p_nested_range": {
          "range": {
            "field": "prices.p",
            "ranges": [
              {
                "from": 0,
                "to": 1000
              },
              {
                "from": 1000,
                "to": 2000
              }
            ]
          }
        }
      }
    },
    "d_range" :{
      "nested": {
        "path": "prices"
      },
      "aggs": {
        "d_nested_range": {
          "range": {
            "field": "prices.d",
            "ranges": [
              {
                "from": 0,
                "to": 500
              },
              {
                "from": 500,
                "to": 1000
              }
            ]
          }
        }
      }
    }
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "nested": {
                "filter": {
                  "bool": {
                    "must": [
                      {
                        "range": {
                          "prices.p": {
                            "gte": 200,
                            "lte": 1400
                          }
                        }
                      }
                    ]
                  }
                },
                "path": "prices",
                "inner_hits": {

                }
              }
            }
          ]
        }
      },
      "query": {
        "match_all": {}
      }
    }
  },
  "sort": {
        "_script" : {
            "type" : "number",
            "script" : {

                "inline": "_source.prices[0].p"

            },
            "order" : "asc"
        }
    }
}