1

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

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

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

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

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

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

4

2 回答 2

2

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:

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. 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):

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:

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.

于 2014-08-13T08:07:47.923 回答
1

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

我建议不要使用数组将这些值存储在一起,因为这是一个“未绑定”的标签数组。未绑定的数组会导致磁盘移动,从而导致更新索引并且操作系统和 mongo 工作。

相反,您应该将每个标签作为单独的文档存储在不同的集合中,并根据相关文档的 _id 对它们进行“存储”。

例子

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

这将允许您使用 db.collection.find({_id : /^<_id>/}) 查询单个用户的所有标签并存储结果。

于 2014-08-12T21:40:02.747 回答