使用mongo同时拉和添加

Sal*_*ali 16 mongodb mongodb-query

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

{tags : [1, 5, 8]}

数组中至少有一个元素,所有元素都应该不同.我想用一个标签替换另一个标签,我认为不会有问题.所以我想出了以下查询:

db.colll.update({
  tags : 1
},{
  $pull: { tags: 1 },
  $addToSet: { tags: 2 }
}, {
  multi: true
})
Run Code Online (Sandbox Code Playgroud)

很酷,所以它会找到所有带有我不需要的标签的元素(1),删除它并添加另一个(2)如果它不存在.问题是我收到一个错误:

"无法同时更新'标签'和'标签'"

这基本上意味着我不能同时做pull和addtoset.有没有其他方法可以做到这一点?

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

Nei*_*unn 18

错误几乎就是它的意思,因为你不能在同一个更新操作中对同一个"路径"的两个东西起作用.您正在使用的两个运算符不会像您认为的那样按顺序处理.

您可以使用"顺序"执行此操作,因为您可以使用"批量"操作API或其他形式的"批量"更新.在理由当然,也是相反的:

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

bulk.execute();
Run Code Online (Sandbox Code Playgroud)

不保证没有其他任何东西会尝试修改,但它与您目前所获得的一样接近.

另请参阅包含多个文档的原始"更新"命令.


Mic*_*ole 5

如果您要同时删除和添加,则可能会对"地图"进行建模,而不是"设置".如果是这样,对象可能比数组少工作.

而不是数据作为数组:

{ _id: 'myobjectwithdata',
  data: [{ id: 'data1', important: 'stuff'},
         { id: 'data2', important: 'more'}]
}
Run Code Online (Sandbox Code Playgroud)

使用数据作为对象:

{ _id: 'myobjectwithdata',
  data: { data1: { important: 'stuff'},
          data2: { important: 'more'} }
}
Run Code Online (Sandbox Code Playgroud)

然后单命令更新:

db.coll.update(
  'myobjectwithdata', 
  { $set: { 'data.data1': { important: 'treasure' } }
);
Run Code Online (Sandbox Code Playgroud)

这里这里完成这个答案的硬脑子.


Xav*_*hot 5

从 开始Mongo 4.4$function聚合运算符允许应用自定义 javascript 函数来实现 MongoDB 查询语言不支持的行为。

再加上对db.collection.update()in 的改进Mongo 4.2,可以接受聚合管道,允许根据自己的值更新字段,

我们可以以语言不允许的方式操作和更新数组:

// { "tags" : [ 1, 5, 8 ] }
db.collection.updateMany(
  { tags: 1 },
  [{ $set:
    { "tags":
      { $function: {
          body: function(tags) { tags.push(2); return tags.filter(x => x != 1); },
          args: ["$tags"],
          lang: "js"
      }}
    }
  }]
)
// { "tags" : [ 5, 8, 2 ] }
Run Code Online (Sandbox Code Playgroud)

$function 需要3个参数:

  • body,这是要应用的函数,其参数是要修改的数组。该功能在这里简单地由在push荷兰国际集团2的阵列和filter荷兰国际集团了1
  • args,其中包含该body函数作为参数的记录字段。在我们的例子中,"$tag".
  • lang,这body是编写函数的语言。仅js当前可用。