首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >聚合组( _parentId )

聚合组( _parentId )
EN

Stack Overflow用户
提问于 2014-08-14 22:15:32
回答 1查看 1.5K关注 0票数 1

我有一个元素列表。一些_parentId属性指向来自同一集合的元素的ids。所以所有拥有_parentId的元素都是那些没有_parentId的元素的子元素。

我需要一个结果,它将包含所有父元素(没有_parentId)、子元素的数量以及最近添加的每个父元素的“dateCreated”属性(它有一个dateCreated属性)。例如:

代码语言:javascript
复制
[{
   _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
}

做这件事的最好方法是什么?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-15 04:46:38

公平的问题。将文档简化一点--例如,假设有这样的文档:

代码语言:javascript
复制
{
    "_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字段,然后对结果进行排序:

代码语言:javascript
复制
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"
        }
    }}
])

由此产生的反应如下:

代码语言:javascript
复制
{
    "_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限制。如果您想要一个类似于发送到其他地方的响应,最好是处理后处理并添加计数,因为您不会有相同的限制,并且可以使用尽可能多的内存。

因此,如果必须的话,那么在最后再添加一个“推”和“计数”组,但不要说当事情出错时,你没有得到更好的建议。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25318412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档