使用 MongoDb 更新插入多条记录
我试图让 MongoDB 通过以下查询更新插入多个记录,最终使用 MongoMapper 和 Mongo ruby 驱动程序。
db.foo.update({event_id: { $in: [1,2]}}, {$inc: {visit:1}}, true, true)
如果所有记录都存在,则此方法可以正常工作,但不会为不存在的记录创建新记录。以下命令在 shell 中具有所需的效果,但在 ruby 驱动程序中可能并不理想。
[1,2].forEach(function(id) {db.foo.update({event_id: id}, {$inc: {visit:1}}, true, true) });
我可以循环遍历要从 ruby 中插入的每个 id,但这需要为每个项目访问数据库。有没有一种方法可以从 ruby 驱动程序中更新插入多个项目,而只需访问数据库一次?这里的最佳实践是什么?使用 mongomapper 和 ruby 驱动程序,有没有办法在一个批次中发送多个更新,生成如下所示的内容?
db.foo.update({event_id: 1}, {$inc: {visit:1}}, true); db.foo.update({event_id: 2}, {$inc: {visit:1}}, true);
样本数据:
如果存在两条记录,则命令后所需的数据。
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 11 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 2 }
如果存在两条记录,则为命令后的实际数据。
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 11 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 2 }
如果仅存在 event_id 1 的记录,则命令后所需的数据。
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 2 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 1 }
如果仅存在 event_id 1 的记录,则命令后的实际数据。
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 2 }
I'm trying to get MongoDB to upsert multiple records with the following query, ultimately using MongoMapper and the Mongo ruby driver.
db.foo.update({event_id: { $in: [1,2]}}, {$inc: {visit:1}}, true, true)
This works fine if all the records exist, but does not create new records for records that do not exist. The following command has the desired effect from the shell, but is probably not ideal from the ruby driver.
[1,2].forEach(function(id) {db.foo.update({event_id: id}, {$inc: {visit:1}}, true, true) });
I could loop through each id I want to insert from within ruby, but that would necessitate a trip to the database for each item. Is there a way to upsert multiple items from the ruby driver with only a single trip to the database? What's the best practice here? Using mongomapper and the ruby driver, is there a way to send multiple updates in a single batch, generating something like the following?
db.foo.update({event_id: 1}, {$inc: {visit:1}}, true); db.foo.update({event_id: 2}, {$inc: {visit:1}}, true);
Sample Data:
Desired data after command if two records exist.
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 11 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 2 }
Actual data after command if two records exist.
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 11 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 2 }
Desired data after command if only the record with event_id 1 exists.
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 2 }
{ "_id" : ObjectId("4d6baf56c0d8bb8238d0209a"), "event_id" : 2, "visit" : 1 }
Actual data after command if only the record with event_id 1 exists.
{ "_id" : ObjectId("4d6babbac0d8bb8238d02099"), "event_id" : 1, "visit" : 2 }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果 event_id 为 1 或 2 的记录尚不存在,则不会插入任何记录
db.foo.update({event_id: { $in: [1,2]}}, {$inc: {visit :1}}, true, true)
这是因为查询的
objNew
部分(参见 http://www.mongodb.org/display/DOCS/Updating#Updating-UpsertswithModifiers) 字段event_id.因此,您将需要至少 X+1 次数据库访问,其中 X 是 event_id 的数量,以确保在特定 event_id 不存在记录时插入一条记录(+1 来自上面的查询) ,这会增加现有记录的访问计数器)。换句话说,MongoDB 如何知道您想要对 event_id 使用值 2 而不是 1?为什么不是 6?
使用 ruby 进行批量插入,我认为这是可能的,如以下链接所示 - 尽管我只使用了 Java 驱动程序: 使用 Mongoid 批量插入/更新?
This - correctly - will not insert any records with event_id 1 or 2 if they do not already exist
db.foo.update({event_id: { $in: [1,2]}}, {$inc: {visit:1}}, true, true)
This is because the
objNew
part of the query (see http://www.mongodb.org/display/DOCS/Updating#Updating-UpsertswithModifiers) does not have a value for fieldevent_id
. As a result, you will need at least X+1 trips to the database, where X is the number of event_ids, to ensure that you insert a record if one does not exist for a particular event_id (the +1 comes from the query above, which increases the visits counter for existing records). To say it in a different way, how does MongoDB know you want to use value 2 for the event_id and not 1? And why not 6?W.r.t. batch insertion with ruby, I think it is possible as the following link suggests - although I've only used the Java driver: Batch insert/update using Mongoid?
您所追求的是 查找和修改 命令,并将 upsert 选项设置为 true 。请参阅 Mongo 测试套件中的示例(同一个链接到在 查找和修改 文档中)的示例看起来非常像您在你的问题中描述。
What you are after is the Find and Modify command with the upsert option set to true. See the example from the Mongo test suite (same one linked to in the Find and Modify docs) for an example that looks very much like what you describe in your question.
我找到了一种使用 eval 运算符来执行服务器端代码的方法。以下是代码片段:
使用
batchpush()
添加多个项目,然后调用batchprocess()
。数据以数组形式发送,命令全部执行。此代码在 MongoDequeue GEM 中使用,位于 此文件。仅发出一个请求,所有更新插入都发生在服务器端。
I found a way to do this using the eval operator for server-side code execution. Here is the code snippit:
Multiple items are added with
batchpush()
, and thenbatchprocess()
is called. The data is sent as an array, and the commands are all executed. This code is used in the MongoDequeue GEM, in this file.Only one request is made, and all the upserts happen server-side.