项目到第二嵌套阵列内的“过滤器”属性(Project to “filter” property wi

2019-10-20 06:26发布

好吧,我一直在试图解决这一段时间,但现在似乎是手忙脚乱。

我的主要目标是潜入第2个嵌套数组和完全删除“isCorrectAnswer”属性...的对象基本上是一个项目,其中有2个问题,各具有3个答案选项...

在应用程序的“回答”的时间表,我需要删除“isCorrectAnswer”,让任何用户可以通过查看数据传递......然后,一旦“应答”的时间表已经过去了,这将返回为作弊完整的对象,来表示答案是正确的那些用户。

从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" }

这工作得很好...

我的下一步是运行$项目中删除“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":{
       "_id":{
           "_id":"$_id",
           "ordinal":"$ordinal",
           "name":"$name",
           "description":"$description",
           "benefits":"$benefits",
           "specialOffer":"$specialOffer",
           "choicePoints":"$choicePoints",
           "bonusPoints":"$bonusPoints",
           "redemptionPoints":"$redemptionPoints",
           "questions":"$questions"
       }
   }}

我仍抓住聚合框架多与$ group命令做......如果有我应该做不同的或如何运行第2 $组到“答案”结合在一起的任何步骤,我想知道。

我也认为我会需要运行一个最终$项目清理那些获得通过$组添加了“_id”属性

谢谢您的帮助。

德里克

Answer 1:

由于您的要求是只是“工程”等等领域被屏蔽的文件,是聚合框架是这样的工具。 这需要一些平仓阵列,虽然重建时,让你的头周围的过程。

所以,你想要的是这样的:

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返回内回答阵列文档,而“isCorrectAnswer”字段。 它使用它自己的变量来表示的元素,并使用$ifNull在那里仅仅是因为“在”的一部分$map运营商期望以评估对每一元素的条件。

总体来说快了一点,因为你不必去通过$unwind$group操作只是为了删除该字段。 因此,它真的成为只是“投影”,你可能期望。



Answer 2:

您可以使用$未设置操作,用点符号相结合,以去除性能。

例如,下面的命令将从第一答案阵列移除isCorrectAnswer属性:

db.collectionname.update({_ ID: “SOME_ID”},{$取消设置:{ “questions.0.answers.0.isCorrectAnswer”: “”}})



文章来源: Project to “filter” property within second nested array