返回每个组的最后一个"true"值

Ama*_*han 5 mongodb mongodb-query aggregation-framework

我收集的文件是这样的:

{
    _id: ObjectId(),
     user: ObjectId(),  
     studentName: String,
     createdAt: Date,
     isAbondoned: boolean
}
Run Code Online (Sandbox Code Playgroud)

文件的例子是:

1-

{ 
    "_id" : ObjectId("56cd2d36a489a5b875902f0e"), 
    "user" : ObjectId("56c4cafabd5f92cd78ae49d4"), 
    "studentName" : "Aman", 
    "createdAt" : ISODate("2016-02-24T04:10:30.486+0000"), 
    "isAbandoned" : true
}
Run Code Online (Sandbox Code Playgroud)

2-

{ 
    "_id" : ObjectId("56cd2dcda489a5b875902fcd"), 
    "user" : ObjectId("56c4cafabd5f92cd78ae49d4"), 
    "studentName" : "Aman",  
    "createdAt" : ISODate("2016-02-24T04:13:01.932+0000"), 
    "isAbandoned" : false
}
Run Code Online (Sandbox Code Playgroud)

3-

{ 
    "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"), 
    "user" : ObjectId("56c85244bd5f92cd78ae4bc1"), 
    "studentName" : "Rajeev",
    "createdAt" : ISODate("2016-02-25T11:27:17.281+0000"), 
    "isAbandoned" : true, 
}
Run Code Online (Sandbox Code Playgroud)

现在我想找到他们的'isAbandoned'对于他们上一个'createdAt'文件是真实的学生名单.

上面示例的必需输出是:

{
    "user" : ObjectId("56c85244bd5f92cd78ae4bc1"), 
    "studentName" : "Rajeev"
}
Run Code Online (Sandbox Code Playgroud)

因为对于studentName"Aman"max(createdAt)是第二个文档而'isAbandoned'是错误的.

sty*_*ane 3

做到这一点的最佳方法是使用聚合框架。您需要按$group“用户”排列文档,并使用累加器运算符返回每个用户的最后一个文档$last,但要使其正常工作,您需要使用$sort聚合管道运算符进行初步排序阶段。要对文档进行排序,您需要考虑“createdAt”字段和“user”字段。

管道中的最后一个阶段是$match您仅选择“isAbandoned”等于的最后文档的阶段true

db.students.aggregate([
    { "$sort": { "user": 1, "createdAt": 1 } }, 
    { "$group": { 
        "_id": "$user", 
        "last": { "$last": "$$ROOT" }
    }}, 
    { "$match": { "last.isAbandoned": true } }
])
Run Code Online (Sandbox Code Playgroud)

它返回类似这样的内容:

{ 
    "_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
    "last" : {
        "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
        "user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
        "studentName" : "Rajeev",
        "createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
        "isAbandoned" : true
    }
}
Run Code Online (Sandbox Code Playgroud)

为了得到预期的结果,我们需要$replaceRoot从3.4版本开始使用管道运算符将嵌入文档提升到顶层

{
    $replaceRoot: { newRoot: "$last" }
}
Run Code Online (Sandbox Code Playgroud)

在旧版本中,您需要使用$project聚合管道操作来重塑我们的文档。因此,如果我们将管道扩展到以下阶段:

{ 
    "$project": { 
        "_id": "$last._id", 
        "user": "$last.user", 
        "studentName": "$last.studentName", 
        "createdAt": "$last.createdAt", 
        "isAbandoned": "$last.isAbandoned"
}}
Run Code Online (Sandbox Code Playgroud)

它产生预期的输出:

{
    "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
    "user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
    "studentName" : "Rajeev",
    "createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
    "isAbandoned" : true
}
Run Code Online (Sandbox Code Playgroud)