首页 > 解决方案 > 计算来自多个条件的命中

问题描述

我将游泳比赛的结果存储在 elasticsearch 中,以便能够以不同的方式分析和呈现数据。每个结果都存储为一个单独的文档,时间以毫秒为单位。像这样:

{
  "swimmer": "xyz123",
  "stroke": "butterfly",
  "distance": 25,
  "time": 20250
}

但是,对于年轻的游泳运动员来说,当他们在五种不同的项目类型(不同的泳姿)中达到一定时间时会获得奖励,我希望能够找到在所有五种项目中的时间都低于指定时间的所有游泳运动员(不同事件的不同时间)。

示例:当一名游泳运动员完成以下任务时获得中杯奖: - 47 秒或更短的 50 米仰泳 - 31 秒或更短的 50 米自由(爬行) - 51 秒或更短的 50 米蛙泳 - 22 秒或更短的 25 米蝶泳 -在 1 分 40 秒或更短的时间内完成 100 米混合泳。

我尝试使用一个 bool/should 查询,该查询由一个 bool/must 查询组成,用于每个笔划的每个限制。在这方面,我在 Swimmer -> Stroke 上有聚合(术语聚合),并且可以根据桶数确定游泳者是否在 5 次冲程中达到了水平。

但是,这会为所有达到任何限制的游泳者返回一个水桶,即使它不是大量的游泳者(还),我发现这从长远来看是行不通的。

我错过了什么(运气不好)?谁能推荐如何在单个查询中实现这一目标?

简化查询:

{
  "query": {
    "bool": {
      "should": [
        { //* backstroke, 50m, <47000ms *// },
        { //* freestroke, 50m, <41000ms *// },
        { //* breaststroke, 50m, <51000ms *// },
        { //* butterfly, 25m, <22000ms *// },
        { //* medley, 100m, <100000ms *// }
      ]
    }
  },
  "aggs": {
    "by_swimmer": {
      "terms": {
        "field": "swimmer"
      },
      "aggs": {
        "by_stroke": {
          "terms": {
            "field": "stroke"
          }
        }
      }
    }
  }
}

标签: elasticsearch

解决方案


该查询返回匹配单个或多个 should 子句的任何文档。您正在创建一个包含单个游泳者的所有文档的存储桶,然后您将按照笔划类型划分这些文档。因为您的初始查询结果包含与任何奖励匹配的所有文档,您最终将得到您描述的结果。有多种方法可以处理这个问题。

  1. 您对每个奖项进行单独查询,在 must 子句中包含过滤器查询。这确保仅选择与奖励过滤器匹配的文档。

  2. 您将查询更改为选择所有文档,例如进行匹配所有。然后你在聚合中处理你的逻辑。您将术语聚合保留在游泳者上,以在一个桶中获取与单个游泳者匹配的所有文档。然后,您对每个奖项在游泳者级别上进行嵌套过滤聚合,如果它们包含游泳者已完成奖项的任何文档。

示例 2:

{
  "query" : {
    "match_all" : {}
  },
  "aggs": {
    "by_swimmer": {
      "terms": {
        "field": "swimmer"
      },
    "aggs": {
      "stroke_award": {
        "filter": {
            "bool": {
              "must": [{ //* backstroke, 50m, <47000ms *// }]
          }
        }
      },
      "freestroke_award": {
        "filter": {
            "bool": {
              "must": [ { //* freestroke, 50m, <41000ms *// }]
            }
          }
        },
        "breaststroke_award": {
          "filter": {
            "bool": {
              "must": [ { //* breaststroke, 50m, <51000ms *// }]
            }
          }
        },
        "butterfly_award": {
          "filter": {
            "bool": {
              "must": [ { //* butterfly, 25m, <22000ms *// }]
            }
          }
        },
          "medley_award": {
          "filter": {
            "bool": {
              "must": [ { //* medley, 100m, <100000ms *// }]
            }
          }
        }
      }
    }
  }
}

如果其中一个桶中有文件,则为游泳者完成奖励。


推荐阅读