Javascript Mongo在单个字段上设置交集,该字段是二维数组

Javascript Mongo在单个字段上设置交集,该字段是二维数组,javascript,mongodb,set,mongodb-query,aggregation-framework,Javascript,Mongodb,Set,Mongodb Query,Aggregation Framework,我在mongo有以下结构的文件。我想得到一个父母中孩子的所有常见日期 {“父”:1,“子”:“a”,“日期”:“2016-02-01”}, {“父”:1,“子”:“a”,“日期”:“2016-02-02”}, {“父”:1,“子”:“a”,“日期”:“2016-02-03”}, {“父”:1,“子”:“b”,“日期”:“2016-02-01”}, {“父”:1,“子”:“b”,“日期”:“2016-02-03”}, {“父”:2,“子”:“a”,“日期”:“2016-02-02”}, {“父母”

我在mongo有以下结构的文件。我想得到一个父母中孩子的所有常见日期

{“父”:1,“子”:“a”,“日期”:“2016-02-01”},
{“父”:1,“子”:“a”,“日期”:“2016-02-02”},
{“父”:1,“子”:“a”,“日期”:“2016-02-03”},
{“父”:1,“子”:“b”,“日期”:“2016-02-01”},
{“父”:1,“子”:“b”,“日期”:“2016-02-03”},
{“父”:2,“子”:“a”,“日期”:“2016-02-02”},
{“父母”:2,“子女”:“a”,“日期”:“2016-02-03”},
{“父”:2,“子”:“b”,“日期”:“2016-02-01”},
{“父”:2,“子”:“b”,“日期”:“2016-02-02”}
为此,我将聚合框架与以下管道一起使用,以获得一个日期数组数组

{
$group:{
_身份证:{
父项:“$parent”,
儿童:$child
},
日期:{
$push:“$date”
}
}
}, {
$group:{
_id:“$\u id.parent”,
日期:{
$push:“$dates”
}
}
}
输出结果如下:

[
{
“_id”:1,
“日期”:[
[ 
"2016-02-01", 
"2016-02-03"
], 
[ 
"2016-02-01", 
"2016-02-02", 
"2016-02-03"
]
]
}, 
{
“_id”:2,
“日期”:[
[ 
"2016-02-01", 
"2016-02-02"
], 
[ 
"2016-02-02", 
"2016-02-03"
]
]
}
]
现在,我想获得每个文档的2d数组中的所有常见日期,并尝试使用
$setcrossion
添加
$projection
阶段。但据我所知,
$setcrossion
需要一个定义良好的字段或数组数组-使用
$setcrossion:“$dates”
无法按预期工作

感谢您的帮助

附加信息:子类型的数量是可变的

预期产出:

[ 
    {
        "_id" : 1.0000000000000000,
        "dates" : [
            "2016-02-01", 
            "2016-02-03"
        ]
    }, 
    {
        "_id" : 2.0000000000000000,
        "dates" : [ 
            "2016-02-02"
        ]
    }
]

使用MongoDB 3.2,您可以获得二维的每个元素,并将其提供给:

db.collection.aggregate([
{“$组”:{
“_id”:{
“父项”:“$parent”,
“child”:“$child”
},
“日期”:{“$push”:“$date”}
}}, 
{“$组”:{
“\u id”:“$\u id.parent”,
“日期”:{“$push”:“$dates”}
}},
{“$project”:{
“日期”:{
“$setcrossion”:[
{“$arrayElemAt”:[“$dates”,0]},
{“$arrayElemAt”:[“$dates”,1]}
]
}
}}
])
但事实上,您所看到的特定问题可以用更简单的方式解决。基本上,你需要做的就是在父对象上计算每个日期发生的子对象。多于一个表示有两个或多个孩子共享日期:

db.collection.aggregate([
{“$组”:{
“_id”:{
“父项”:“$parent”,
“日期”:“$date”
},
“计数”:{“$sum”:1}
}},
{“$match”:{“count”:{“$gt”:1}}},
{“$组”:{
“\u id”:“$\u id.parent”,
“日期:{“$push”:“$\u id.date”}
}}
])    
因此没有理由比较数组,因为一个简单的分组元素计数告诉您“集合交集”是什么

同样的原则也适用于引入聚合框架的每个MongoDB版本

两者都会产生相同的结果:

{u id:1,“日期”:[“2016-02-03”,“2016-02-01”]}
{“_id”:2,“日期”:[“2016-02-02”]}

还要注意的是,“集合”不被认为是有序的,从
$group

发出的键的顺序也不被认为是有序的。这里可以做的是计算父级的子级数量,并计算父级的每个子级的日期数量

然后获取所有日期,其中日期数等于父级的子级数,这将给出预期的输出

这是我尝试过的,但可能有更好的解决方案

db.coll.aggregate([
    {
        $group: {
            _id: {
                parent: "$parent",
                child: "$child"
            },
            dates: {
                $push: "$date"
            }
        }
    },
    {
        $group: {
            _id: "$_id.parent",
            total_children: {$sum : 1},
            dates: {
                $push: "$dates"
            }
        }
    },
    {
        $unwind : "$dates"
    },
    {
        $unwind : "$dates"
    },
    {
        $group : {
            _id : {
                parent : "$_id",
                dates : "$dates"
            },
            total_children : {$first : "$total_children"},
            total_dates : {$sum : 1}
        }
    },
    {
        $project : {
            _id : 1,
            tempEq : {$eq : ["$total_children", "$total_dates"]}
        }
    },
    {
        $match : {'tempEq' : true}
    },
    {
        $group : {
            _id : '$_id.parent',
            dates : {$addToSet : "$_id.dates"}
        }
    }
])
这将产生以下输出:

{ "_id" : 1, "dates" : [ "2016-02-01", "2016-02-03" ] }
{ "_id" : 2, "dates" : [ "2016-02-02" ] }

希望这能有所帮助。

您能编辑您的问题,将预期的输出文档也包括在内吗?非常感谢!第一个我不能使用,因为数组元素的数量没有定义,可以有多个子元素。第二个是一个开心果!这是如此简单,正是我所需要的!我不知道我在想什么:)@arawind真正的问题是,第二个过程与你正在做的事情是一样的,从不同的角度来看。嘿,谢谢,但公认的答案要简单得多:)欢迎。。在我的情况下,我假设你的父母可能有两个以上的孩子。:)你的假设是正确的,被接受答案的后半部分就是答案。如果我没有错的话,你也在遵循类似的方法?而且可能您的大多数聚合阶段都可以合并为一个。。