我如何计算mongo集合中具有相交子集合的项目?

问题描述 投票:1回答:1

对于我的收藏夹中的每个物品,我都需要查找其他具有相交子收藏夹的其他物品的数量。例如,给定这个集合

[{id:1,"sub":[1, 2, 3]},
{id:2,"sub":[2, 3, 4]},
{id:3,"sub":[4, 5, 6],
{id:4,"sub":[7, 8, 9]}]

预期结果是

[{id:1,"count":1},
{id:2,"count":2},
{id:3,"count":1},
{id:4,"count":0"}]
c# .net mongodb mongodb-query mongodb-.net-driver
1个回答
0
投票

[从纯MongoDB查询语言的算法开始:您必须重组文档,以便每个文档包含其初始sub数组和所有其他sub值的数组。为此,您需要同时运行$group$unwind。然后,只需将$map$setIntersect全部清空并等于自身数组,然后使用$filter

获得大小即可运行$size
db.collection.aggregate([
    {
        $group: {
            _id: null,
            current: { $push: "$$ROOT" },
            all: { $push: "$sub" }
        }
    },
    {
        $unwind: "$current"
    },
    {
        $project: {
            id: "$current.id",
            count: {
                $size: {
                    $filter: {
                        input: {
                            $map: {
                                input: "$all",
                                in: { $setIntersection: [ "$$this", "$current.sub" ] }
                            }
                        },
                        cond: {
                            $and: [ 
                                { $ne: [ "$$this", [] ] },
                                { $ne: [ "$$this", "$current.sub" ]}
                            ]
                        }
                    }
                }
            }
        }
    }
])

Mongo Playground

由于聚合非常复杂,因此在C#中以强类型的方式运行它毫无意义。您所能做的就是使用BsonDocument类来构建管道,例如:

var groupDef = new BsonDocument()
        {
            { "_id", "" },
            { "current", new BsonDocument(){ { "$push", "$$ROOT" } } },
            { "all", new BsonDocument(){ { "$push", "$sub" } } },
        };

var projectDef = BsonDocument.Parse(@"{
        id: ""$current.id"",
        _id: 0,
        count: {
        $size: {
            $filter: {
            input: {
                $map: {
                input: ""$all"",
                in: {
                    $setIntersection: [
                    ""$$this"",
                    ""$current.sub""
                    ]
                }
                }
            },
            cond: {
                $and: [
                {
                    $ne: [
                    ""$$this"",
                    []
                    ]
                },
                {
                    $ne: [
                    ""$$this"",
                    ""$current.sub""
                    ]
                }
                ]
            }
            }
        }
        }
    }");

var result = mongoDBCollection.Aggregate()
                                .Group(groupDef)
                                .Unwind("current")
                                .Project(projectDef)
                                .ToList();
© www.soinside.com 2019 - 2024. All rights reserved.