有条件地处理mongodb组中的项目(聚合管道)

时间:2016-05-06 08:27:49

标签: javascript mongodb aggregation-framework

考虑一个包含调查结果的MongoDB集合,其结果是 feedback (任意数量的自由文本答案)或 multi (用户可以选择全部,没有或一些提供的答案)。所有问题都有一个唯一的名称,答案的类型和答案对于该特定名称保持一致。

考虑这组示例条目:

{ 
    "_id" : ObjectId("572c4af25e30ae25a0307df0"), 
    "question" : "Q1", 
    "type" : "feedback", 
    "answers" : [
        "feedback value 1", 
        "feedback value 2"
    ]
}
{ 
    "_id" : ObjectId("572c4b7a5e30ae25a0307dfa"), 
    "question" : "Q1", 
    "type" : "feedback", 
    "answers" : [
        "feedback value 2"
    ]
}
{ 
    "_id" : ObjectId("572c4b885e30ae25a0307dfc"), 
    "question" : "Q2", 
    "type" : "feedback", 
    "answers" : [
        "feedback value 1"
    ]
}
{ 
    "_id" : ObjectId("572c4ba65e30ae25a0307dfe"), 
    "question" : "Q3", 
    "type" : "multi", 
    "answers" : [
        {
            "value" : "A1", 
            "chosen" : true
        }, 
        {
            "value" : "A2", 
            "chosen" : false
        }
    ]
}
{ 
    "_id" : ObjectId("572c4c125e30ae25a0307e00"), 
    "question" : "Q3", 
    "type" : "multi", 
    "answers" : [
        {
            "value" : "A1", 
            "chosen" : false
        }, 
        {
            "value" : "A2", 
            "chosen" : false
        }
    ]
}

我想要的是创建某种评估聚合,其中结果应如下所示(每个答案都有一个结果文档):

{
  "_id": "Q1",
  "type:" "feedback",
  // list of _unique_ values
  "answers": ["feedback value 1", "feedback value 2"]
}
// Q2 omitted for the sake of shortness
{
  "_id": "Q3",
  "type:" "multi",
  // list of all answers with selection count, including the never-chosen ones
  "answers": {
     "A1": 1,
     "A2": 0 
  }
}

那么如何创建这样的聚合呢?我首先想到了map-reduce,但是正如每个人都说我应该更喜欢聚合管道,我试了一下。

我的第一步是按问题ID分组("问题"字段)。然后,我想添加到组阶段中与 feedback multi 调查的答案类型相对应的其他字段。另一个"投影"然后,阶段应为输出选择适当的字段。

db.survey.aggregate(
    [
        // Stage 1
        {
            $group: {
                _id: "$question",
                type: {
                    $first: "$type"
                },
                answersFeedback: {
                    // this creates nested arrays 
                    // instead of an array of strings
                    $addToSet: {
                        $cond: [{
                            $eq: ["$type", "feedback"]
                        }, "$answers", []]
                    }
                },
                // no idea how to achieve this
                answersMulti: {
                    $first: {
                        $literal: {
                            "foo": 42
                        }
                    }
                }
            }
        },

        // Stage 2
        {
            $project: {
                "type": 1,
                // select answer field according to type
                "answers": {
                    $cond: [{
                        $eq: ["$type", "multi"]
                    }, "$answersMulti", "$answersFeedback"]
                }
            }
        }

    ]
);

不幸的是,反馈答案导致嵌套数组

{ 
    "_id" : "Q2", 
    "type" : "feedback", 
    "answers" : [
        [
            "feedback value 1"
        ]
    ]
}

我不知道如何处理多票。你能帮我继续吗?

数据库在v3.2.4服务器上运行。使用的模式(数据格式)是实际数据的简化版本,我可能不会修改它,我确实必须按原样处理。

0 个答案:

没有答案