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

时间:2014-08-12 18:25:04

标签: mongodb casbah mongodb-update

搜索后,我无法弄清楚如何对单个字段执行多个更新。

我有一个带有"标签的文件"数组字段。在开始更新之前,每个文档都会有随机标记。在单个操作中,我想添加一些标签并删除一些标签。

以下更新运算符返回错误"指定的无效修饰符:$和"

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

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

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

2 个答案:

答案 0 :(得分:2)

您不需要$and更新查询,但是您无法同时使用更新更新两个字段 - 正如您在shell中尝试以下内容时所看到的那样:

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

您会收到Cannot update 'tags' and 'tags' at the same time错误消息。那么如何实现呢?使用此模式,您需要在多个操作中执行此操作,您可以使用新的bulk operation 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();

或者在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()

它不是原子的,并且不能保证没有其他任何东西会尝试修改,但它就像你现在所能得到的那样接近。

答案 1 :(得分:1)

Mongo进行原子更新,因此您可以在数组中构建所需的标记,然后替换整个数组。

我建议不要使用数组来存储这些值,因为这是一个"未绑定的"标签数组。未绑定的数组会导致磁盘上的移动,从而导致索引更新,操作系统和mongo可以正常工作。

相反,您应该将每个标记作为单独的文档存储在不同的集合中,并且#34; bucket"它们基于相关文件的_id。

示例

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

这将允许您使用db.collection.find({_ id:/ ^&lt; _id&gt; /})查询单个用户的所有标记并将结果存储起来。