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

如何在MongoDB聚合中基于flagField:true去除用户半重复文档

问题:基于flagField:true去重用户的半重复文档

原始集合数据

[
    {
        "userId": 1,
        "flagField": false,
        "extraField": "1"
    },
    {
        "userId": 1,
        "flagField": true,
        "extraField": "2"
    },
    {
        "userId": 1,
        "flagField": true,
        "extraField": "3"
    },
    {
        "userId": 1,
        "flagField": false,
        "extraField": "4"
    },
    {
        "userId": 2,
        "flagField": true,
        "extraField": "1"
    }
]

期望结果

[
    {
        "userId": 1,
        "flagField": true,
        "extraField": "2"
    },
    {
        "userId": 2,
        "flagField": true,
        "extraField": "1"
    }
]

需求说明

需要筛选出flagField: true的文档,并且对同一userId只保留完整的原始文档(所有字段来自同一条原始记录),同一用户有多条符合条件的文档时,任选其一即可。

解决方案

方法1:$match + $group 组合

先过滤出符合条件的文档,再按userId分组,直接保留完整原始文档:

db.collection.aggregate([
    // 第一步:筛选flagField为true的文档
    { $match: { flagField: true } },
    // 第二步:按userId分组,取每组第一个完整文档(换$last可取最后一个)
    {
        $group: {
            _id: "$userId",
            doc: { $first: "$$ROOT" }
        }
    },
    // 第三步:把完整文档作为根文档输出
    { $replaceRoot: { newRoot: "$doc" } }
])
  • $$ROOT代表当前整条原始文档,$first: "$$ROOT"会保留分组后每组的第一条完整记录,满足“所有字段来自同一原始文档”的要求。

方法2:$setWindowFields(支持自定义排序后选文档)

如果需要先对每组内的文档排序(比如按extraField排序)再选取,可用窗口函数实现:

db.collection.aggregate([
    { $match: { flagField: true } },
    {
        $setWindowFields: {
            partitionBy: "$userId",
            sortBy: { extraField: 1 }, // 按extraField升序排序,可自定义规则
            output: {
                rowNumber: { $rowNumber: {} }
            }
        }
    },
    { $match: { rowNumber: 1 } }, // 只保留每组的第一条文档
    { $unset: "rowNumber" } // 移除临时添加的行号字段
])

这种方式可以先对分组内的文档排序,再选取指定位置的完整文档,灵活性更高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:57:33