拉,并在同一时间蒙戈addtoset拉,并在同一时间蒙戈addtoset(Pull and addt

2019-05-12 07:05发布

我有哪些元素可以简化为这样一个集合:

{tags : [1, 5, 8]}

那里将是阵列的至少一个元件和所有的人都应该是不同的。 我想替换一个标签为另一个,我认为不会有问题。 于是我想出了以下查询:

db.colll.update({
  tags : 1
},{
  $pull: { tags: 1 },
  $addToSet: { tags: 2 }
}, {
  multi: true
})

酷,所以它会发现其中有一个我不需要(1),将其删除,并添加一个标签的所有元素另一个(2)如果不存在的话。 问题是,我得到一个错误:

“无法更新‘标签’和‘标签’在同一时间”

这基本上意味着,我不能在同一时间做拉和addtoset。 是否有其他方法可以让我做到这一点?

当然,我可以记住元素的所有ID,然后删除标签,并添加单独的查询,但这并不听起来不错。

Answer 1:

该错误是相当多的是什么意思,你不能在相同的更新操作相同的“路径”的两件事情采取行动。 您正在使用的两个运营商,你可能会认为他们不按顺序处理。

您可以为“连续”,你可以可能与获得这样做“批量”操作的API “批量”更新的或其他形式,虽然。 在合理范围内,当然,也反向:

var bulk = db.coll.initializeOrderedBulkOp();
bulk.find({ "tags": 1 }).updateOne({ "$addToSet": { "tags":  2 } });
bulk.find({ "tags": 1 }).updateOne({ "$pull": { "tags": 1 } });

bulk.execute();

不能保证什么都没尝试修改,但它是接近你现在会得到。

还看到原始的“更新”命令与多个文档。



Answer 2:

如果要删除,并在同一时间加入,您可能会建模一个“地图”,而不是“设置”。 如果是这样,一个对象可能比阵列工作较少。

代替数据为阵列的:

{ _id: 'myobjectwithdata',
  data: [{ id: 'data1', important: 'stuff'},
         { id: 'data2', important: 'more'}]
}

使用数据作为一个对象:

{ _id: 'myobjectwithdata',
  data: { data1: { important: 'stuff'},
          data2: { important: 'more'} }
}

一命令更新则是:

db.coll.update(
  'myobjectwithdata', 
  { $set: { 'data.data1': { important: 'treasure' } }
);

硬脑这个答案做的工作在这里和这里 。



文章来源: Pull and addtoset at the same time with mongo