集合文档中不同子类型的集合 [英] Aggregate of different subtypes in document of a collection

查看:99
本文介绍了集合文档中不同子类型的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出的集合md中的抽象文档:

abstract document in collection md given:

{
    vals : [{
        uid : string,
        val : string|array
    }]
}

给出以下部分正确的汇总:

the following, partially correct aggregation is given:

db.md.aggregate(
    { $unwind : "$vals" },
    { $match : { "vals.uid" : { $in : ["x", "y"] } } },
    {
        $group : { 
            _id : { uid : "$vals.uid" },
            vals : { $addToSet : "$vals.val" }

        }
    }
);

这可能会导致以下结果:

that may lead to the following result:

"result" : [
    {
        "_id" : {
            "uid" : "x"
        },
        "vals" : [
            [
                "24ad52bc-c414-4349-8f3a-24fd5520428e",
                "e29dec2f-57d2-43dc-818a-1a6a9ec1cc64"
            ],
            [
                "5879b7a4-b564-433e-9a3e-49998dd60b67",
                "24ad52bc-c414-4349-8f3a-24fd5520428e"
            ]
        ]
    },
    {
        "_id" : {
            "uid" : "y"
        },
        "vals" : [
            "0da5fcaa-8d7e-428b-8a84-77c375acea2b",
            "1721cc92-c4ee-4a19-9b2f-8247aa53cfe1",
            "5ac71a9e-70bd-49d7-a596-d317b17e4491"
        ]
    }
]

由于x是在包含数组而不是字符串的文档上聚合的结果,因此结果中的val是数组的数组.在这种情况下,我要寻找的是一个扁平数组(如y的结果).

as x is the result aggregated on documents containing an array rather than a string, the vals in the result is an array of arrays. what i look for in this case is to have a flattened array (like the result for y).

对我来说,似乎我仅想通过一个聚集调用来实现的目标,目前尚不受任何给定操作的支持,例如在每种情况下都无法完成类型转换或释放期望的数组作为输入类型.

for me it seems like that what i want to achieve by one aggegration call only, is currently not supported by any given operation as e.g. a type conversion cannot be done or unwind expectes in every case an array as input type.

地图会减少我唯一的选择吗?如果没有...任何提示吗?

is map reduce the only option i have? if not ... any hints?

谢谢!

推荐答案

您可以使用聚合来执行所需的计算,而无需更改架构(尽管您可能会考虑更改架构,只是为了简化此字段的查询和聚合)来写).

You can use the aggregation to do the computation you want without changing your schema (though you might consider changing your schema simply to make queries and aggregations of this field easier to write).

出于可读性考虑,我将管道分解为多个步骤.为了便于阅读,我还对您的文档进行了一些简化.

I broke up the pipeline into multiple steps for readability. I also simplified your document slightly, again for readability.

样本输入:

> db.md.find().pretty()
{
    "_id" : ObjectId("512f65c6a31a92aae2a214a3"),
    "uid" : "x",
    "val" : "string"
}
{
    "_id" : ObjectId("512f65c6a31a92aae2a214a4"),
    "uid" : "x",
    "val" : "string"
}
{
    "_id" : ObjectId("512f65c6a31a92aae2a214a5"),
    "uid" : "y",
    "val" : "string2"
}
{
    "_id" : ObjectId("512f65e8a31a92aae2a214a6"),
    "uid" : "y",
    "val" : [
        "string3",
        "string4"
    ]
}
{
    "_id" : ObjectId("512f65e8a31a92aae2a214a7"),
    "uid" : "z",
    "val" : [
        "string"
    ]
}
{
    "_id" : ObjectId("512f65e8a31a92aae2a214a8"),
    "uid" : "y",
    "val" : [
        "string1",
        "string2"
    ]
}

管道阶段:

> project1 = {
    "$project" : {
        "uid" : 1,
        "val" : 1,
        "isArray" : {
            "$cond" : [
                {
                    "$eq" : [
                        "$val.0",
                        [ ]
                    ]
                },
                true,
                false
            ]
        }
    }
}
> project2 = {
    "$project" : {
        "uid" : 1,
        "valA" : {
            "$cond" : [
                "$isArray",
                "$val",
                [
                    null
                ]
            ]
        },
        "valS" : {
            "$cond" : [
                "$isArray",
                null,
                "$val"
            ]
        },
        "isArray" : 1
    }
}
> unwind = { "$unwind" : "$valA" }
> project3 = {
    "$project" : {
        "_id" : 0,
        "uid" : 1,
        "val" : {
            "$cond" : [
                "$isArray",
                "$valA",
                "$valS"
            ]
        }
    }
}

最终汇总:

> db.md.aggregate(project1, project2, unwind, project3, group)
{
    "result" : [
        {
            "_id" : "z",
            "vals" : [
                "string"
            ]
        },
        {
            "_id" : "y",
            "vals" : [
                "string1",
                "string4",
                "string3",
                "string2"
            ]
        },
        {
            "_id" : "x",
            "vals" : [
                "string"
            ]
        }
    ],
    "ok" : 1
}

这篇关于集合文档中不同子类型的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆