简体   繁体   English

Casbah MongoDB,如何在单个操作中向数组添加和删除值到多个文档?

[英]Casbah MongoDB, how to both add and remove values to an array in a single operation, to multiple documents?

After searching, I was unable to figure out how to perform multiple updates to a single field. 搜索之后,我无法弄清楚如何对单个字段执行多个更新。

I have a document with a "tags" array field. 我有一个带有“tags”数组字段的文档。 Every document will have random tags before I begin the update. 在开始更新之前,每个文档都会有随机标记。 In a single operation, I want to add some tags and remove some tags. 在单个操作中,我想添加一些标签并删除一些标签。

The following update operator returns an error "Invalid modifier specified: $and" 以下更新运算符返回错误“指定的无效修饰符:$和”

    updateOperators: { "$and" : [
      { "$addToSet" : { "tags" : { "$each" : [ "tag_1" , "tag_2"]}}},
      { "$pullAll" : { "tags" : [ "tag_2", "tag_3"]}}]}  

    collection.update(query, updateOperators, multi=true)  

How do I both add and remove values to an array in a single operation, to multiple documents? 如何在单个操作中向多个文档添加和删除数组?

You don't need the $and with the update query, but you cannot update two fields at the same time with an update - as you would see if you tried the following in the shell: 您不需要$and更新查询,但是您无法同时使用更新更新两个字段 - 正如您在shell中尝试以下操作时所看到的那样:

db.test.update({}, { "$addToSet" : { "tags" : { "$each" : [ "tag_1" , "tag_2"]}}, 
                     "$pullAll"  : { "tags" : [ "tag_2", "tag_3"] }}, true, false)

You would get a Cannot update 'tags' and 'tags' at the same time error message. 您将Cannot update 'tags' and 'tags' at the same time错误消息。 So how to achieve this? 那么如何实现呢? Well with this schema you would need to do it in multiple operations, you could use the new bulk operation api as shown below (shell): 使用此模式,您需要在多个操作中执行此操作,您可以使用新的批量操作api ,如下所示(shell):

var bulk = db.coll.initializeOrderedBulkOp();
bulk.find({ "tags": 1 }).updateOne({ "$addToSet": { "$each" : [ "tag_1" , "tag_2"]}});
bulk.find({ "tags": 1 }).updateOne({ "$pullAll": { "tags": [ "tag_2", "tag_3"] } });
bulk.execute();

Or in Casbah with the dsl helpers: 或者在Casbah中使用dsl助手:

val bulk = collection.initializeOrderedBulkOperation
bulk.find(MongoDBObject("tags" -> 1)).updateOne($addToSet("tags") $each("tag_1", tag_2"))
bulk.find(MongoDBObject("tags" -> 1)).updateOne($pullAll("tags" -> ("tags_2", "tags_3")))
bulk.execute()

Its not atomic and there is no guarantee that nothing else will try to modify, but it is as close as you will currently get. 它不是原子的,并且不能保证没有其他任何东西会尝试修改,但它与你目前得到的一样接近。

Mongo does atomic updates so you could just construct the tags you want in the array and then replace the entire array. Mongo进行原子更新,因此您可以在数组中构建所需的标记,然后替换整个数组。

I would advise against using an array to store these values all together as this is an "unbound" array of tags. 我建议不要使用数组来存储这些值,因为这是一个“未绑定”的标签数组。 Unbound arrays cause movement on disk and that causes indexes to be updated and the OS and mongo to do work. 未绑定的数组会导致磁盘上的移动,从而导致索引更新,操作系统和mongo可以正常工作。

Instead you should store each tag as a seperate document in a different collection and " bucket " them based on the _id of the related document. 相反,您应该将每个标记作为单独的文档存储在不同的集合中,并根据相关文档的_id“ 存储 ”它们。

Example

{_id : <_id> <key> <value>} - single docuemnt

This will allow you to query for all the tags for a single user with db.collection.find({_id : /^<_id>/}) and bucket the results. 这将允许您使用db.collection.find({_ id:/ ^ <_ id> /})查询单个用户的所有标记并存储结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM