在MongoDB中,将项目添加到数组并删除任何重复项目的好方法是什么?
如果项目已经在数组中,则 $addToSet
不会执行任何操作。
这个SO question显示了两种前置方式,但不会删除欺骗。
使用Mongo 2.4.1,MongoMapper和Ruby。
答案 0 :(得分:1)
您可以通过限定update
条件来实现此目的,以包括前置值不在数组中。然后将$push
与$each
和$position
一起使用,您可以在数组的开头插入该项,只要该数组尚未存在于数组中。
假设文档看起来像:
{
"_id": 1,
"a": [1]
}
您可以在shell中执行更新:
var value = 1;
db.test.update(
{_id: 1, a: {$ne: value}},
{$push: {a: {$each: [value], $position: 0}}})
对于value
为1的情况没有效果,但任何其他值都将添加到a
数组字段之前。
答案 1 :(得分:1)
$addToSet
运算符当然不会删除现有的重复项,也不会删除" set"是任何被认为是有序的元素,因此无法用这个算子来定位它们。
在任何一种情况下,按照你的逻辑来处理重复项现在由你来管理。但是bulk operations API可以帮助你,而不是拉动文档并在代码中操作,这可能会导致并发问题。
因此,为了确保您的逻辑,您可以使用$pull
从您插入的数组中删除任何项目,然后使用$push
,使用需要的$position
修饰符与$each
修饰符结合使用。
一个基本的mongomapper代码示例:
require 'mongo_mapper'
require 'pp'
MongoMapper.database = 'test'
class User
include MongoMapper::Document
key :array, Array
end
User.collection.remove
user = User.create(:array => [5, 4, 4, 6])
pp user
bulk = User.collection.initialize_unordered_bulk_op
bulk.find(:_id => user._id, :array => 4)
.update_one({ "$pull" => { "array" => 4 }})
bulk.find({"_id" => user._id, "array" => { "$ne" => 4 }})
.update_one({
"$push" => {
"array" => { "$each" => [4], "$position" => 0 }
}
})
res = bulk.execute()
pp res
pp user.reload
严格地说,这仍然不是原子操作,而是在多次更新中执行。但API实现确实通过线路将这两个请求一起发送,并连续实现它们。因此,这与您目前将获得逻辑的原子操作非常接近。
此示例中的结果数组当然是:
array: [4, 5, 6]