给定以下MongoDB集合:
{
"_id": ObjectId("56d6a7292c06e85687f44541"),
"name": "My ranking list",
"rankings": [
{
"_id": ObjectId("46d6a7292c06e85687f55542"),
"name": "Ranking 1",
"score": 1
},
{
"_id": ObjectId("46d6a7292c06e85687f55543"),
"name": "Ranking 2",
"score": 10
},
{
"_id": ObjectId("46d6a7292c06e85687f55544"),
"name": "Ranking 3",
"score": 15
},
]
}
以下是我如何提高给定排名的分数:
db.collection.update(
{ "_id": ObjectId("56d6a7292c06e85687f44541"), "rankings._id" : ObjectId("46d6a7292c06e85687f55543") },
{ $inc : { "rankings.$.score" : 1 } }
);
如何获得新的分数值?在上一个查询中,我将第二个排名从10增加到11…更新后如何获取这个新值?
最佳答案
如果您在MongoDB 3.0或更高版本上,则需要使用.findOneAndUpdate()
并使用projection
选项指定要返回的字段子集。您还需要将returnNewDocument
设置为true
。当然,您需要在这里使用$elemMatch
投影运算符,因为您不能使用位置投影并返回新文档。
正如有人指出的:
您应该使用.findOneAndUpdate()
,因为.findAndModify()
在每个官方语言驱动程序中都被高调标记为已弃用。另一件事是,.findOneAndUpdate()
的驱动程序的语法和选项非常一致。对于.findAndModify()
,大多数驱动程序不使用具有“query/update/fields”键的同一单个对象。所以当有人应用到另一种语言以保持一致时,就不那么令人困惑了。.findOneAndUpdate()
的标准化API更改实际上对应于服务器3.x版,而不是3.2.x版。完全区别在于shell方法实际上落后于其他驱动程序(仅此一次!)在实现方法时。因此,大多数驱动程序实际上都有一个与3.x版本相对应的主要版本凸起,并进行了这样的更改。
db.collection.findOneAndUpdate(
{
"_id": ObjectId("56d6a7292c06e85687f44541"),
"rankings._id" : ObjectId("46d6a7292c06e85687f55543")
},
{ $inc : { "rankings.$.score" : 1 } },
{
"projection": {
"rankings": {
"$elemMatch": { "_id" : ObjectId("46d6a7292c06e85687f55543") }
}
},
"returnNewDocument": true
}
)
从MongoDB 3.0开始,您需要使用
findAndModify
和fields
选项,还需要在Other中将new
设置为true
以返回新值。db.collection.findAndModify({
query: {
"_id": ObjectId("56d6a7292c06e85687f44541"),
"rankings._id" : ObjectId("46d6a7292c06e85687f55543")
},
update: { $inc : { "rankings.$.score" : 1 } },
new: true,
fields: {
"rankings": {
"$elemMatch": { "_id" : ObjectId("46d6a7292c06e85687f55543") }
}
}
})
两个查询都产生:
{
"_id" : ObjectId("56d6a7292c06e85687f44541"),
"rankings" : [
{
"_id" : ObjectId("46d6a7292c06e85687f55543"),
"name" : "Ranking 2",
"score" : 11
}
]
}