如何对MongoDB文档的字段进行原子更新?

3
免责声明:我对Mongo和数据库总体都不太了解,如果我的术语或概念有误,请告诉我。
为了举例说明,我想将鼠标坐标存储在一个文档内的嵌套对象中。该文档将类似于以下样式:
{ "_id" : ObjectId("4f39805d35919a2a7c7aba3e"), "mouseLoc" : { "x" : 10, "y" : 20 } }

似乎通过修改器操作进行原子更新是可行的,因为我只在此处存储值(在其他软件中检索它们)。但是,我无法弄清楚查询部分。如何访问此文档以设置x和y值?我正在使用Java,所以我目前尝试: (链接)
BasicDBObject mouseLoc = new BasicDBObject();
mouseLoc.put("x", mouseX);
mouseLoc.put("y", mouseY);
myCollection.update(queryObj, new BasicDBObject("$set", mouseLoc), true, false);

然而,我不知道如何指定该queryObj以获取具有mouseLoc键的文档。或者,如果有一种更聪明的存储此类信息的方法,请指导我。
如果更简单的话,我可以跟随Mongo shell/JS提示。
更新:如果我给它一个静态字段像“name”,我可以查询这个文档。所以,要更新此文档:
{ "_id" : ObjectId("4f39805d35919a2a7c7aba3e"), "name" : "mouseLoc", "mouseLoc" : { "x" : 10, "y" : 20 } }

我可以使用这段代码:

BasicDBObject mouseLoc = new BasicDBObject();
mouseLoc.put("x", mouseX);
mouseLoc.put("y", mouseY);

BasicDBObject queryObj = new BasicDBObject("name", "mouseLoc");
BasicDBObject updateObj = new BasicDBObject("$set", new BasicDBObject("mouseLoc", mouseLoc));

myCollection.update(queryObj, updateObj, true, false);

然而,似乎没有必要指定“name”字段才能使用“mouseLoc”键检索文档。也许我只是误解了数据库/ mongo设计?

2个回答

0

查询部分是您指定查找文档的方式,例如: _id 或其他唯一字段。

在您的示例中,它将如下所示:

ObjectId objectId = new ObjectId("4f39805d35919a2a7c7aba3e");
BasicDBObject queryObj = new BasicDBObject("_id", objectId);

(也许关于ObjectId有些遗漏,因为我不懂Java。)

更新

如果您正在搜索特定的mouseLoc,则queryObj将是非常mouseLoc对象。(在JSON中,它将是{'x':mouseX,'y':mouseY}。)


ObjectId实际上只是从shell find()中直接复制过来的,它不是Java的东西。是的,这就是我使用查询参数的方式。但是,我想仅检索具有某些“mouseLoc”键的文档,而不考虑其值。我是否误解了数据库设计?我必须拥有一个唯一的名称-值对,例如您的“_id”示例或我的更新,其中使用“name”字段吗? - ericsoco
@ericsoco 要从其 mouseLoc 检索某些文档,请将其设置为 queryObj。但是,如果您要更新到新的 X 和 Y,则会有两个 mouseLocmouseLocBeforequeryObj)和 mouseLocAfter(更新对象),您可以在同一更新命令中同时使用两者:myCollection.update(mouseLocBefore, mouseLocAfter, true, false); - Sony Santos
我不想使用 mouseLoc 去检索一个文档;我正在更新到新的 X 和 Y。我不一定知道以前的 X 和 Y,例如当我重新启动应用程序并写入鼠标坐标时。简而言之,我不想仅为了写入新状态就存储先前的状态。听起来像是我需要某个已知状态(键 + 值)才能检索文档。正确吗? - ericsoco
1
你需要一些字段来标识你的文档。我想你的收藏中有许多文档,每个文档都有不同的mouseLoc。你如何区分每个mouseLoc的用途?例如:这是图像上的mouseLoc;那是点击按钮时的mouseLoc等。或者:这是时间T的mouseLoc,那是时间W的mouseLoc。你需要一个查询字段来标识你的mouseLoc含义。如果你的收藏中只有一个文档,你可以使用一个空对象。如果你的收藏中只有一个带有mouseLoc的文档,查询对象将使用$exists - Sony Santos
$exists 就是我一直在寻找的。看了 $exists 的文档(http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24exists),发现它效率不高。这很有道理,我现在明白了,我的文档应该有一个带有唯一值的字段来标识文档,并可能提示其用途。感谢您坚持让我理解这一点 ;) - ericsoco
@ericsoco 我在阅读... 在你的情况下,$exists 不是低效的(只有一个带有 mouseLoc 的文档)。文档中说:“... 因为它实际上必须扫描所有索引值”,但在这种特殊情况下,只有一个文档需要在 mouseLoc 上进行索引。无论如何,随意根据您的需求对数据库进行建模。MongoDB 给了我们足够的自由! :) - Sony Santos

0

使用.限定符怎么样?

myCollection.updateOne(Document.parse("{ \"_id\" : ObjectId(\"4f39805d35919a2a7c7aba3e\")}"),
    Document.parse("{$set:{ \"mouseLoc.x\" : "+mouseX+", \"mouseLoc.y\" : "+mouseY+" }")
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接