考虑一个包含调查结果的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服务器上运行。使用的模式(数据格式)是实际数据的简化版本,我可能不会修改它,我确实必须按原样处理。