mongodb 将$COND和$EQ用于对象数组

von4xj4u  于 2022-12-12  发布在  Go
关注(0)|答案(2)|浏览(148)

我希望有人能够回答我下面尝试完成的工作是否可以用MongoDB聚合框架来完成。
我有一个用户数据结构,它类似于下面的用户数据结构,其中包含将近100万个文档。

{
    "firstName" : "John",
    "lastName" : "Doe",
    "state" : "NJ",
    "email" : "JOHNDOE@XYZ.COM"
    "source" : [ 
        {
            "type" : "SOURCE-A",
            "data" : {
                "info" : "abc",
                "info2" : "xyz"
            }
        }, 
        {
            "type" : "SOURCE-B",
            "data" : {
                "info3" : "abc"
            }
        }
    ]
}

为了将数据提供给另一个系统,我需要生成一个平面文件结构,其中包含来自前一个数据集的有限信息。

firstname, lastname, email, is_source-a, is_source-b

我遇到困难的部分是尝试填充“is_source-a”和“is_source-b”的条件代码。我尝试使用以下聚合查询,但无法弄清楚如何使其工作,因为与$COND沿着使用的$EQ操作符似乎不计算数组内的数据(总是false)。

db.collection.aggregate([
    {
        $project : {
            _id : 0,
            firstName : 1,
            lastName: 1,
            "is_source-a" : {
                $cond : [
                    { $eq: [ "$source.type", "source-a" ] },
                    1,
                    0
                ]
            },
            "is_source-b" : {
                $cond : [
                    { $eq: [ "$source.type", "source-b" ] },
                    1,
                    0
                ]
            }
        }
    }
]);

我可以先$UNWIND数组,但这样一来,每个用户文档都有多个记录,而且不知道如何将它们合并回来。
在处理对象数组时,我在如何使用$EQ(或其他操作符)沿着$COND方面是否遗漏了什么?

3df52oht

3df52oht1#

您的思路肯定是正确的,如果您继续使用$group将所有东西重新组合在一起,那么使用$unwind可以帮助您实现这一目标:

db.collection.aggregate([
    {$unwind: '$source'},
    {$project: {
        _id: 1,
        firstName: 1,
        lastName: 1,
        email: 1,
        'is_source-a': {$eq: ['$source.type', 'SOURCE-A']},
        'is_source-b': {$eq: ['$source.type', 'SOURCE-B']}
    }},
    // group the docs that were duplicated in the $unwind back together by _id,
    // taking the values for most fields from the $first occurrence of the _id,
    // but the $max of the is_source fields so that if its true in any of the
    // docs for that _id it will be true in the output for that _id.
    {$group: {
        _id: '$_id',
        firstName: {$first: '$firstName'},
        lastName: {$first: '$lastName'},
        email: {$first: '$email'},
        'is_source-a': {$max: '$is_source-a'},
        'is_source-b': {$max: '$is_source-b'}
    }},
    // project again to remove _id
    {$project: {
        _id: 0,
        firstName: 1,
        lastName: 1,
        email: 1,
        'is_source-a': '$is_source-a',
        'is_source-b': '$is_source-b'
    }}
])
w9apscun

w9apscun2#

如果您不想使用$unwind$group,也可以使用$cond$in来实现。
我在这里找到了这个https://www.mongodb.com/community/forums/t/cond-inside-an-array-is-not-working/156468
我有点惊讶这是可行的,但正如mongo docs所述:

$in
 has the following operator expression syntax:

{ $in: [ <expression>, <array expression> ] }

对于最初的问题(我相信8年后你还在等这个问题),可以这样做:

db.collection.aggregate([
    {
        $project : {
            _id : 0,
            firstName : 1,
            lastName: 1,
            "is_source-a" : {
                $cond : [
                    { $in: [ "source-a", "$source.type" ] },
                    1,
                    0
                ]
            },
            "is_source-b" : {
                $cond : [
                    { $in: [ "source-b", "$source.type" ] },
                    1,
                    0
                ]
            }
        }
    }
]);

相关问题