【问题标题】:Group documents by value from another field按来自另一个字段的值对文档进行分组
【发布时间】:2019-08-12 15:02:46
【问题描述】:

我有

格式的文件
{
    "_id": <some_id>,
    "code": <some_code>,
    "manually_updated": {
        "code": <some_code>
    }
}

我想通过查看根code 值以及manually_updated.code 字段来查找重复项( 文档)。因此,以下三个文档将被视为重复文件(第二个文档 code 通过将代码添加到 manually_updated 被“覆盖”,code 与第一个和第三个文档相同):

{
    {
        "_id" : ObjectId("5d2dc168651ce400a327b408"),
        "code": 'ABCD',
        "manually_updated": {}
    },
    {
        "_id" : ObjectId("5d40861411981f0068e22511"),
        "code": 'EFGH',
        "manually_updated": {
            "code": "ABCD"
        }
    },
    {
        "_id" : ObjectId("5d41374311981f0163779b79"),
        "code": 'ABCD',
        "manually_updated": {}
    }
}

谢谢。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework mongoengine


    【解决方案1】:

    请试试这个:

        db.getCollection('yourCollection').aggregate([{
        $lookup:
        {
            from: "yourCollection",
            let: { codeToBeCompared: "$code", manualCode: '$manually_updated.code' },
            pipeline: [
                {
                    $match:
                    {
                        $expr:
                        {
    
                            $or:
                                [
                                    { $eq: ["$code", "$$codeToBeCompared"] },
                                    { $eq: ["$manually_updated.code", "$$codeToBeCompared"] },
                                    { $and: [{ $gt: ['$manually_updated', {}] }, { $eq: ["$manually_updated.code", '$$manualCode'] }] }
                                ]
                        }
                    }
                }
    
            ],
            as: "data"
        }
    }, { $group: { _id: '$code', manually_updated: { $push: '$manually_updated' }, finalData: { $first: '$$ROOT' } } }, { $match: { $expr: { $gt: [{ $size: "$finalData.data" }, 1] } } },
       { $project: { 'manually_updated': 1, 'data': '$finalData.data' } }])
    

    示例文档:

    /* 1 */
    {
        "_id" : ObjectId("5d2dc168651ce400a327b408"),
        "code" : "ABCD",
        "manually_updated" : {}
    }
    
    /* 2 */
    {
        "_id" : ObjectId("5d40861411981f0068e22511"),
        "code" : "EFGH",
        "manually_updated" : {
            "code" : "ABCD"
        }
    }
    
    /* 3 */
    {
        "_id" : ObjectId("5d41374311981f0163779b79"),
        "code" : "ABCD",
        "manually_updated" : {}
    }
    
    /* 4 */
    {
        "_id" : ObjectId("5d518a3ce8078d6134c4cd21"),
        "code" : "APPPP",
        "manually_updated" : {}
    }
    
    /* 5 */
    {
        "_id" : ObjectId("5d518a3ce8078d6134c4cd22"),
        "code" : "APPPP",
        "manually_updated" : {
            "code" : "ABCD"
        }
    }
    
    /* 6 */
    {
        "_id" : ObjectId("5d518a3ce8078d6134c4cd23"),
        "code" : "APPPP",
        "manually_updated" : {}
    }
    
    /* 7 */
    {
        "_id" : ObjectId("5d518a3ce8078d6134c4cd24"),
        "code" : "deffffff",
        "manually_updated" : {}
    }
    

    输出:

    /* 1 */
    {
        "_id" : "APPPP",
            "manually_updated" : [ // Preserving this to say we've passed thru these values
                {},
                {
                    "code": "ABCD"
                },
                {}
            ],
                "data" : [
                    {
                        "_id": ObjectId("5d518a3ce8078d6134c4cd21"),
                        "code": "APPPP",
                        "manually_updated": {}
                    },
                    {
                        "_id": ObjectId("5d518a3ce8078d6134c4cd22"),
                        "code": "APPPP",
                        "manually_updated": {
                            "code": "ABCD"
                        }
                    },
                    {
                        "_id": ObjectId("5d518a3ce8078d6134c4cd23"),
                        "code": "APPPP",
                        "manually_updated": {}
                    }
                ]
    }
    
    /* 2 */
    {
        "_id" : "EFGH",
            "manually_updated" : [
                {
                    "code": "ABCD"
                }
            ],
                "data" : [
                    {
                        "_id": ObjectId("5d40861411981f0068e22511"),
                        "code": "EFGH",
                        "manually_updated": {
                            "code": "ABCD"
                        }
                    }
                ]
    }
    
    /* 3 */
    {
        "_id" : "ABCD",
            "manually_updated" : [
                {},
                {}
            ],
                "data" : [
                    {
                        "_id": ObjectId("5d2dc168651ce400a327b408"),
                        "code": "ABCD",
                        "manually_updated": {}
                    },
                    {
                        "_id": ObjectId("5d40861411981f0068e22511"),
                        "code": "EFGH",
                        "manually_updated": {
                            "code": "ABCD"
                        }
                    },
                    {
                        "_id": ObjectId("5d41374311981f0163779b79"),
                        "code": "ABCD",
                        "manually_updated": {}
                    },
                    {
                        "_id": ObjectId("5d518a3ce8078d6134c4cd22"),
                        "code": "APPPP",
                        "manually_updated": {
                            "code": "ABCD"
                        }
                    }
                ]
    }
    

    这也会扫描所有内容,您可以将$match 作为第一阶段,根据特定代码过滤文档。

    【讨论】:

    • srinivasy 我错过了 manually_updated.code 相同的文档也应该被分组(即使根 code 不同)。您如何将这种情况添加到您的回复中?谢谢
    • @HugoSousa : 所以一个新组只在manual_updated.code上,不管代码是什么?
    • 是的,所以{"code": "foo", "manually_updated": {"code": "duplicate"}}{"code": "bar", "manually_updated": {"code": "duplicate"}} 也会将它们分组为重复项。
    • @HugoSousa:manual_updated 会是一个空对象吗?那么这将是一个问题,空对象确实映射到其他空对象,如果它不是空的,您可以尝试通过添加这些 ::> 在 let part ::::> manualCode: '$manually_updated.code' 和$or :::> { $eq: ["$manually_updated.code", '$$manualCode'] } ,如果我找到一种基于非空对象映射的方法,我会更新给你
    • @HugoSousa :好的,问题太多了:-),好吧,一切正常,即;添加了您的新场景并删除了数据不是数组的文档(如果您不需要,请在最后删除 $match),请测试并告诉我..!!
    猜你喜欢
    • 2018-07-19
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 2023-01-12
    • 2021-12-17
    • 2015-09-21
    • 1970-01-01
    • 2013-01-11
    相关资源
    最近更新 更多