1

我创建了一个关于使用 $match 的主题,该主题已解决,但现在我陷入了一个更复杂的示例。例如,考虑我的 Json 的结构:

{
    user: 'bruno',
    answers: [
        {id: 0, value: 3.5},
        {id: 1, value: "hello"}
    ]
}

我想添加或排序,对“value”中包含的值应用一些转换,仅标识符“id”等于 0,例如排序方法。

考虑以下数据:

db.my_collection.insert({ user: 'bruno', answers: [ {id: 0, value: 3.5}, {id: 1, value: "hello"}]})

db.my_collection.insert({ user: 'bruno2', answers: [ {id: 0, value: 0.5}, {id: 1, value: "world"}]})

我尝试使用:

db.my_collection.aggregate ({$sort: {"answers": {"$elemMatch": {id: 0, value: -1}}}})

但是,它没有用。预期结果是:{user: 'bruno2' answers: [{id: 0, value: 0.5}, {id: 1, value: "world"}]}, {user: 'bruno' answers: [{id: 0,值:3.5},{id:1,值:“你好”}]})

谢谢你。

4

1 回答 1

7

首先,请注意您的排序示例格式错误:聚合方法将数组作为输入,其中数组中的每个元素指定聚合管道中的一个阶段。另外,请注意$elemMatch运算符不能用作 $sort 阶段的一部分。

实现排序示例的一种方法是使用聚合框架的$unwind管道运算符。展开数组会将数组元素一个接一个地剥离到单独的文档中。例如,以下查询

db.my_collection.aggregate([ {$unwind: "$answers"} ]);

返回如下内容:

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 1,
            "value" : "hello"
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 1,
            "value" : "world"
        }
    }
]

添加 $match 阶段将允许您仅获取 answers.id 为零的文档。最后,$sort 阶段允许您按 answers.value 排序。聚合查询一起是:

db.my_collection.aggregate([
    {$unwind: "$answers"},
    {$match: {"answers.id": 0}},
    {$sort: {"answers.value": -1}}
]);

和输出:

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    }
]

根据您的要求,听起来您并不总是需要 $unwind 甚至聚合框架。相反,如果您想查找 answers.id 等于 0 且 answers.value 等于 3.5 的文档,然后将 answers.value 更改为 4,您可以使用 find 和 $elemMatch,然后是 db.collection.save():

doc = db.my_collection.findOne({"answers": {$elemMatch: {"id": 0, "value": 3.5}}});
for (i=0; i<doc.answers.length; i++) {
  if (doc.answers[i].id === 0) {
    doc.answers[i].value = 4;
    db.my_collection.save(doc);
    break;
  }
}
于 2013-09-16T16:13:17.630 回答