限制$ lookup mongo上的字段

时间:2017-11-13 16:27:21

标签: javascript node.js mongodb mongoose aggregation-framework

我有一个带有以下架构的Mongo对象。

nn.Sequential

“作者”和“参与者”字段是具有以下架构的另一个集合的外键引用。

{
    "_id" : "59fffda313d02500116e83bf::5a059c67f3ff3b001105c509",
    "quizzes" : [ 
        {
            "topics" : [ 
                ObjectId("5a05a1e1fc698f00118470e2")
            ],
            "isCorrect" : true,
            "status" : 2,
            "isUsed" : true,
            "askBack" : false,
            "isRestricted" : false,
            "rejected" : false,
            "createdAt" : ISODate("2017-11-10T12:56:01.273Z"),
            "updatedAt" : ISODate("2017-11-10T12:56:02.808Z"),
            "answerRead" : false,
            "participantAnswer" : "5a054210d74fe90011d5f5e2",
            "correctAnswer" : "5a054210d74fe90011d5f5e2",
            "question" : ObjectId("5a054210d74fe90011d5f5e0"),
            "participant" : ObjectId("59fffda313d02500116e83bf"),
            "author" : ObjectId("5a059c67f3ff3b001105c509"),
            "_id" : ObjectId("5a05a1e1fc698f00118470e1")
        }, 
        {
            "topics" : [ 
                ObjectId("5a054210d74fe90011d5f5e1")
            ],
            "isCorrect" : false,
            "status" : 2,
            "isUsed" : true,
            "askBack" : true,
            "isRestricted" : false,
            "rejected" : false,
            "createdAt" : ISODate("2017-11-10T12:57:33.910Z"),
            "updatedAt" : ISODate("2017-11-10T12:57:33.910Z"),
            "answerRead" : true,
            "correctAnswer" : "5a054210d74fe90011d5f5e2",
            "question" : ObjectId("5a054210d74fe90011d5f5e0"),
            "participant" : ObjectId("5a059c67f3ff3b001105c509"),
            "author" : ObjectId("59fffda313d02500116e83bf"),
            "_id" : ObjectId("5a05a23dfc698f00118470f5")
        }
    ],
    "participants" : [ 
        ObjectId("5a059c67f3ff3b001105c509"), 
        ObjectId("59fffda313d02500116e83bf")
    ],
    "__v" : 0,
    "skippedQuestionIds" : []
}

我需要在第一个集合上运行聚合并限制测验子文档中的对象数量,并在updatedAt时间戳上对其进行排序。

我还想从users集合中填充quizzes数组中每个元素内的作者和参与者。但是,我很难检索到我需要的字段,即只有username,firstName,lastName,_id,meta和active。

我做到了这一点。

{
"_id" : ObjectId("5739bcdd4fb7d8030050bc04"),
"password" : "$2a$06$4Rmiya6Vh9aENXxKoD56UOIG3ZiGNzH.Ed5lgY8aiJ4OidQPAf6wq",
"email" : "m@m.com",
"username" : "mm",
"birthday" : ISODate("2016-05-03T18:30:00.000Z"),
"lastName" : "m",
"firstName" : "m",
"devices" : [],
"role" : "user",
"updatedAt" : ISODate("2017-08-01T13:26:43.510Z"),
"createdAt" : ISODate("2016-05-16T12:28:13.063Z"),
"lastUpdated" : ISODate("2017-08-02T07:39:02.960Z"),
"active" : false,
"points" : 0,
"topicLocked" : [ 
    "flirty", 
    "dirty", 
    "mahesh_test"
],
"hashfriends" : [],
"blockedList" : [],
"friends" : [ 
    {
        "user" : ObjectId("586b6fd12631000004812a68"),
        "_id" : ObjectId("58e60399ca9a180004072089"),
        "topicExhausted" : [],
        "scoreInPercentage" : 0,
        "totalQuizAnswered" : 1,
        "isCrew" : false,
        "isFriendo" : false,
        "scoreRank" : "You’re tied 1 to 1",
        "score" : 1,
        "lastPlayed" : ISODate("2017-04-06T09:37:48.843Z")
    }
],
"meta" : {
    "totalInvites" : -3,
    "totalFriends" : 1
},
"isDeleted" : false,
"__v" : 3,
"androidDevices" : [],
"iosDevices" : [],
"isAgeRestrictedCategories" : [ 
    ObjectId("571727dde30aef0300a95725")
],
"usernameAsEntered" : "mm",
"platform" : "ios",
"celebParticipants" : [],
"lastActivity" : ISODate("2017-04-06T09:30:34.054Z"),
"lastNudged" : ISODate("2016-04-25T06:46:38.267Z")
}

然而,这是我想要的回应。

db.getCollection('usergames').aggregate([{$match: {_id: "5a059c56f3ff3b001105c508::5a059c67f3ff3b001105c509"}},
{$unwind: '$quizzes'},
{$lookup: {
    "from":'users',
    "localField":'quizzes.author',
    'foreignField': '_id',
    "as": 'quizzes.author'
}},
{$unwind: '$quizzes.author'},
{$sort: {'quizzes.updatedAt': -1}},
{$group: {_id: '$_id', quizzes: {$push: '$quizzes'}}},
{$project: {
  _id: 1,
  'quizzes': {
            $slice:['$quizzes', 0, 3]
  }}
}
])

可以在初始投影后完成查找,以及如何限制字段。任何帮助将不胜感激。感谢

1 个答案:

答案 0 :(得分:0)

我不熟悉你的架构以完成整个管道,但是如果我可以概括一点:

是的,$lookup可以在$project操作后完成。您可以在聚合中进行多个$project操作(实际上是多个操作)。

$lookup操作之后可能会进行$project操作,以便按以下方式规范化您的结果:

{$lookup: {
    "from":'users',
    "localField":'quizzes.author',
    'foreignField': '_id',
    "as": 'authors'
}},
{$project: {
    'author._id': { $arrayElemAt: ['$authors._id', 0] },
    'author.username': { $arrayElemAt: ['$authors.username', 0] },
    // other fields can be projected as needed
}},

由于$lookup在数组中返回结果,上面的示例使用$arrayElemAt来获取第一个元素并逐个投影所需的属性。