我有一个元素列表。一些_parentId属性指向来自同一集合的元素的ids。所以所有拥有_parentId的元素都是那些没有_parentId的元素的子元素。
我需要一个结果,它将包含所有父元素(没有_parentId)、子元素的数量以及最近添加的每个父元素的“dateCreated”属性(它有一个dateCreated属性)。例如:
[{
_id: "some id",
title: "some title",
email: "some email",
dateCreated: "date",
children:{
count: 7,
lastAddedChildContent: "some content",
dateCreated: "date:
}],
parentCount:23 // total for parent elements
}做这件事的最好方法是什么?谢谢!
发布于 2014-08-15 04:46:38
公平的问题。将文档简化一点--例如,假设有这样的文档:
{
"_id" : ObjectId("53ed7efca75ca1a5248a281a"),
"dateCreated" : ISODate("2014-08-15T03:46:57.784Z"),
"title" : "Master",
"content" : "Orig content"
}
{
"_id" : ObjectId("53ed80bba75ca1a5248a281b"),
"title" : "Other title",
"content" : "More content",
"dateCreated" : ISODate("2014-08-15T03:38:35.694Z"),
"_parent" : ObjectId("53ed7efca75ca1a5248a281a")
}
{
"_id" : ObjectId("53ed80d1a75ca1a5248a281c"),
"title" : "Other title",
"content" : "Last content",
"dateCreated" : ISODate("2014-08-15T03:38:57.750Z"),
"_parent" : ObjectId("53ed7efca75ca1a5248a281a")
}聚合管道将从本质上替代适合父级的_id字段,然后对结果进行排序:
db.collection.aggregate([
{ "$project": {
"_id": { "$ifNull": [ "$_parent", "$_id" ] },
"title": 1,
"dateCreated": 1,
"content": 1,
"_parent": { "$ifNull": [ "$_parent", false ] }
}},
{ "$sort": { "_id": 1, "_parent": -1, "dateCreated": 1 } },
{ "$group": {
"_id": "$_id",
"title": { "$min": { "$cond": [ "$_parent", false, "$title" ] } },
"dateCreated": {
"$max": {
"$cond": [
"$_parent",
false,
"$dateCreated"
]
}
},
"childCount": {
"$sum": {
"$cond": [
"$_parent",
1,
0
]
}
},
"lastContent": { "$last": "$content" },
"lastDate": { "$last": "$dateCreated" }
}},
{ "$project": {
"title": 1,
"dateCreated": 1,
"children": {
"count": "$childCount",
"lastContent": "$lastContent",
"dateCreated": "$lastDate"
}
}}
])由此产生的反应如下:
{
"_id" : ObjectId("53ed7efca75ca1a5248a281a"),
"title" : "Master",
"dateCreated" : ISODate("2014-08-15T03:46:57.784Z"),
"children" : {
"count" : 2,
"lastContent" : "Last content",
"dateCreated" : ISODate("2014-08-15T03:38:57.750Z")
}
}要查看的主要操作符是$ifNull,它测试字段的存在或实际上是一个null值,并返回字段内容或备用参数。另一个是$cond,它是一个三值算子。它计算一个逻辑条件或值,因为它是第一个参数,然后在该参数为true的情况下返回第二个参数,或者返回最后一个参数,其中false。在现代发行版中,这甚至可以写成“如果.那么.否则”,如果看起来更清楚的话。
最初的$project从本质上是为$sort提供信息,这基本上是在您需要$last操作符来构成响应的一部分时完成的。
在$group语句中,属于“父”的所有文档现在都具有与父文档相同的_id,因此这是正确的分组键。任何“父字段”都有条件地计算,因此只返回该内容,这在$min上是一种创造性的使用,因为“字符串”只返回“父”文档,并且其值将小于否则返回的false值。
子文档的“计数”是在选择要传递给$sum的值时对文档是否为“父”的简单评估。与count一起的其他字段由排序顺序的$last计算,所有字段都分别返回,因为不能在聚合组中返回“子文档”表单。这些$project稍后进入所需的输出。
我故意把日期搞得乱七八糟,以演示“排序”原则的一部分,但这主要是关于“家长”的识别。另一种深思熟虑的做法不是将所有“父”都分组到一个数组中。我不认为这是一个很好的做法,仅仅得到一个计数,它运行一个真正的可能性打破16 to的BSON限制。如果您想要一个类似于发送到其他地方的响应,最好是处理后处理并添加计数,因为您不会有相同的限制,并且可以使用尽可能多的内存。
因此,如果必须的话,那么在最后再添加一个“推”和“计数”组,但不要说当事情出错时,你没有得到更好的建议。
https://stackoverflow.com/questions/25318412
复制相似问题