MongoDb: $push/$addToSet的区别

93

我阅读了MongoDb的文档,并使用了一个简单的方法,我只看到: push对数组排序,但addToSet不会。

在视觉上对我来说是一样的,我不知道区别。

有人能解释一下区别吗?

另外,如果能用西班牙语或简单英语,我将不胜感激。


4
$push 永远不会对数组进行排序。 $push$addToSet 都会将新元素添加到目标数组的末尾。 - Leonid Beschastny
6个回答

153

$addToSet 如果给定的字段已经包含该项,则不会将其添加进去,而$push无论该字段是否存在都会将对象添加到该字段中。

{_id: "docId", items: [1, 2]}
db.items.update({_id:"docId"}, {$addToSet:{items: 2}}); // This won't update the document as it already contains 2
db.items.update({_id:"docId"}, {$push: {items:2}}); // this will update the document. new document {_id: "docId", items:[1,2,2]}

1
谢谢您的解释,现在我正在做另一个例子,这次我更理解了。 - Emilio López
另外,$addToSet 不会影响现有的重复元素。 - Deepak Sah

34

$push - 将项目按照接收顺序添加。您还可以多次添加相同的项目。

$addToSet - 仅添加唯一项目,但不保证项目顺序。

如果您需要按顺序添加唯一项目,可以通过 $addToSet 对元素进行分组和添加,然后使用带有元素的 $unwind 数组,$sort 按项排序,然后再次使用 $group 和 $push 项。


3

除了其他人提到的差异之外,

  • $push:将对象附加到数组中
  • $addToSet:仅在不存在时将对象添加到数组中

在复制方面有所不同。(可以通过查看 local.oplog.rs 来了解)

  • 实际修改数组的 $push 操作将被复制为 $set.items.INDEX:item
  • 实际修改数组的 $addToSet 操作将被复制为 $set.items:[THE_ENTIRE_ARRAY]

如果你要处理大型数组,则这种差异可能会很显著。

因此,尽管像(维护唯一数组的典型用例)

db.items.updateOne(
  {_id: 'my-id', 'items': {'$ne': 'items1'},
  {'$push': {
    'items': 'item1',
  }}
)

db.items.updateOne(
  {_id: 'my-id'},
  {'$addToSet': {
    'items': 'item1',
  }}
)

可能最终会得到相同的文档,但复制操作有所不同。


2
正如其名称所示,$addToSet(集合)不允许重复项,而$push只是将元素添加到数组中。

2

$addToSet 和 $push 做的事情是一样的,但是 $push 会将任何项都推送进去,忽略重复的内容,导致冗余。前者只会推送唯一的项,不会有重复。


0

$push:将值插入到结果文档中的数组中。例如:

db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])

$addToSet:将值插入到结果文档中的数组中,但不创建重复项。 例如:

db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接