You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过单条Elasticsearch查询实现考试数据去重多字段计数

答案

可以,整套筛选、去重、统计逻辑完全可以通过单条Elasticsearch查询实现,不需要拆分多次请求。


具体实现思路

你可以通过「过滤+terms分组聚合+top_hits子聚合+分组内条件计数」的组合完成所有需求,三步业务逻辑和ES能力的映射关系如下:

  • 对应第一步条件筛选:不需要先拉全量记录再筛人,直接在聚合层做前置过滤,拿到所有存在Physics = "Fail"记录的Roll no集合,自动排除所有物理成绩全及格的学生(也就是示例里的学号2),再反向匹配这些学号对应的全量考试记录即可。
  • 对应第二步按学号去重:基于筛选出的学号集合,以Roll no做terms分组,每组通过top_hits子聚合取1条任意记录(size设为1,不指定排序规则就满足“不限制保留考试场次”的要求),这一步返回的结果和给出的去重示例结构完全一致。
  • 对应第三步分科目Pass人数统计:在每个Roll no的分组内做过滤计数,统计对应科目值为Pass的数量时,自动忽略值为Not available的记录,最后把各分组的计数累加就是最终结果。

参考查询结构(简化版)

POST /exam_records/_search
{
  "size": 0,
  "aggs": {
    "qualified_rollnos": {
      "terms": {
        "field": "Roll no",
        "size": 10000,
        "include": {
          "partition": 0,
          "num_partitions": 1
        }
      },
      "aggs": {
        "has_physics_fail": {
          "filter": {
            "term": {
              "Physics": "Fail"
            }
          }
        },
        "dedup_record": {
          "top_hits": {
            "size": 1,
            "_source": ["Exam", "Name", "Roll no", "English", "Hindi", "Physics", "Maths"]
          }
        },
        "bucket_filter": {
          "bucket_selector": {
            "buckets_path": {
              "failCount": "has_physics_fail>_count"
            },
            "script": "params.failCount > 0"
          }
        },
        "english_pass": {
          "filter": {
            "bool": {
              "must": [{"term": {"English": "Pass"}}],
              "must_not": [{"term": {"English": "Not available"}}]
            }
          }
        },
        "hindi_pass": {
          "filter": {
            "bool": {
              "must": [{"term": {"Hindi": "Pass"}}],
              "must_not": [{"term": {"Hindi": "Not available"}}]
            }
          }
        },
        "physics_pass": {
          "filter": {
            "bool": {
              "must": [{"term": {"Physics": "Pass"}}],
              "must_not": [{"term": {"Physics": "Not available"}}]
            }
          }
        },
        "maths_pass": {
          "filter": {
            "bool": {
              "must": [{"term": {"Maths": "Pass"}}],
              "must_not": [{"term": {"Maths": "Not available"}}]
            }
          }
        }
      }
    }
  }
}

返回结果里,dedup_record就是去重后的单条学生记录,各*_pass子聚合的doc_count累加值就是对应科目的及格人数,和给出的预期结果完全匹配。

补充说明:因为当前去重规则不限制保留哪场考试的记录,只要保证每个学号仅取1条参与统计,结果就符合业务要求。如果后续需要固定取某场考试(比如最晚的mid-term 3),只需要在top_hits里加对应排序规则即可,统计逻辑不需要改动。

内容的提问来源于stack exchange,提问作者user3401007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:36:21