好的,我一直试图解决这个问题,但似乎是在圈子里跑。
我的主要目标是深入第二个嵌套数组并完全删除'isCorrectAnswer'属性...该对象基本上是一个项目,它有2个问题,每个问题有3个答案选项......
在应用程序的“回答”时间范围内,我需要删除'isCorrectAnswer',以便没有用户可以通过查看正在传递的数据来作弊...然后一旦'回答'时间框架已经过去,这将是作为完整对象返回,以向用户指示哪些答案是正确答案。
“item”对象的一个示例,其中包含从MongoDB返回的问题和答案:
{
"_id" : ObjectId("5397e4b75c4c9bf0509709ab"),
"name" : "Item Name",
"description" : "Item Description",
"questions" : [
{
"_id" : ObjectId("5397eb925d2664177b0fc5a5"),
"question" : "Item Question 1",
"answers" : [
{
"_id" : ObjectId("5397eb925d2664177b0fc5a6"),
"answer" : "Item Question 1 - Answer 1",
"isCorrectAnswer" : true
},
{
"_id" : ObjectId("5397eb925d2664177b0fc5a7"),
"answer" : "Item Question 1 - Answer 2",
"isCorrectAnswer" : false
},
{
"_id" : ObjectId("5397eb925d2664177b0fc5a8"),
"answer" : "Item Question 1 - Answer 3",
"isCorrectAnswer" : false
}
]
},
{
"_id" : ObjectId("5397eb925d2664177b0fc5a9"),
"question" : "Item Question 2",
"answers" : [
{
"_id" : ObjectId("5397eb925d2664177b0fc5aa"),
"answer" : "Item Question 2 - Answer 1",
"isCorrectAnswer" : false
},
{
"_id" : ObjectId("5397eb925d2664177b0fc5ab")
"answer" : "Item Question 2 - Answer 2",
"isCorrectAnswer" : true
},
{
"_id" : ObjectId("5397eb925d2664177b0fc5ac"),
"answer" : "Item Question 3 - Answer 3",
"isCorrectAnswer" : false
}
]
}
]
}
现在,根据我从MongoDB课程中学到的知识......
我的第一个目标是进行双重展开,将所有内容展平为单个对象结构。
首先,聚合管道中的步骤是:
{ "$unwind": "$questions" },
{ "$unwind": "$questions.answers" }
这很好......
我的下一步是运行$ project来删除'isCorrectAnswer'属性:
{ "$project": {
"_id":1,
"name":1,
"description":1,
"questions":{
"_id":"$questions._id",
"question":"$questions.question",
"answers":{
"_id":"$questions.answers._id",
"answer":"$questions.answers.answer"
}
}
}}
这也很好......
现在我不知所措的是将对象重新组合到原始结构中(没有'isCorrectAnswer'属性)......
我可以在管道中接下来运行这个$ group命令,该命令可以正常工作,但答案没有用他们的问题重新分组
{ "$group":{
"_id":{
"_id":"$_id",
"ordinal":"$ordinal",
"name":"$name",
"description":"$description",
"benefits":"$benefits",
"specialOffer":"$specialOffer",
"choicePoints":"$choicePoints",
"bonusPoints":"$bonusPoints",
"redemptionPoints":"$redemptionPoints",
"questions":"$questions"
}
}}
我仍在掌握聚合框架,更多的是与$ group命令有关...我想知道是否有任何步骤我应该做的不同或如何运行第二个$组来将'答案'组合在一起
我还假设我需要运行一个最终的$项目来清理通过$ group添加的'_id'属性
感谢您的帮助。
德里克
答案 0 :(得分:2)
因为你的要求只是"项目"该文件使字段被屏蔽,是的,聚合框架是用于执行此操作的工具。在展开数组和重构时,需要花点时间了解过程。
所以你想要的是:
db.collection.aggregate([
{ "$unwind": "$questions" },
{ "$unwind": "$questions.answers" },
{ "$group": {
"_id": {
"_id": "$_id",
"name": "$name",
"description": "$description",
"qid": "$questions._id",
"question": "$questions.question"
},
"answers": {
"$push": {
"_id": "$questions.answers._id",
"answer": "$questions.answers.answer"
}
}
}},
{ "$project": {
"questions": {
"_id": "$_id.qid",
"question": "$_id.question",
"answers": "$answers"
}
}},
{ "$sort": { "_id": 1, "questions._id": 1 } },
{ "$group": {
"_id": "$_id._id",
"name": { "$first": "$_id.name" },
"description": { "$first": "$_id.description" },
"questions": { "$push": "$questions" }
}}
])
但实际上,如果您有MongoDB 2.6或更高版本,那么您不需要将$unwind
和$group
结果重新组合在一起以省略该字段。您现在可以使用$project
和使用数组的$map
运算符来执行此操作:
db.collection.aggregate([
{ "$project": {
"name": 1,
"description": 1,
"questions": {
"$map": {
"input": "$questions",
"as": "q",
"in": {
"$ifNull": [
{
"_id": "$$q._id",
"question": "$$q.question",
"answers": {
"$map": {
"input": "$$q.answers",
"as": "el",
"in": {
"$ifNull": [
{ "_id": "$$el._id", "answer": "$$el.answer" },
false
]
}
}
}
},
false
]
}
}
}
}}
])
很抱歉在那里稍微滚动页面的缩进,但通过比较它仍然更容易阅读。
第一个$map
处理问题数组并将其提供给内部$map
,内部$ifNull
返回内部答案数组文档而不使用" isCorrectAnswer"领域。它使用它自己的变量来表示元素,而$map
的用法只是因为" in" $unwind
运算符的一部分期望评估每个元素的条件。
整体速度要快一些,因为您不必通过$group
和{{3}}操作来删除字段。所以它真的变成了"投影"你可能会期待的。
答案 1 :(得分:0)
您可以使用 $ unset 运算符,结合点表示法来删除属性。
例如,以下命令将从第一个答案数组中删除isCorrectAnswer属性:
db.collectionname.update({_ ID:" SOME_ID"},{$取消设置:{" questions.0.answers.0.isCorrectAnswer":"&# 34;}})