Mongodb 使用mongo同时拉动和添加设置
我有一个集合,其中的元素可以简化为:Mongodb 使用mongo同时拉动和添加设置,mongodb,mongodb-query,Mongodb,Mongodb Query,我有一个集合,其中的元素可以简化为: {tags:[1,5,8]} 数组中至少有一个元素,并且所有元素都应该不同。我想用一个标签替换另一个,我认为这不会有问题。因此,我提出了以下问题: db.colll.update({ tags : 1 },{ $pull: { tags: 1 }, $addToSet: { tags: 2 } }, { multi: true }) 很酷,所以它会找到所有有我不需要的标签的元素(1),删除它,如果它还没有,再添加一个(2)。问题是我得到了一
{tags:[1,5,8]}
数组中至少有一个元素,并且所有元素都应该不同。我想用一个标签替换另一个,我认为这不会有问题。因此,我提出了以下问题:
db.colll.update({
tags : 1
},{
$pull: { tags: 1 },
$addToSet: { tags: 2 }
}, {
multi: true
})
很酷,所以它会找到所有有我不需要的标签的元素(1),删除它,如果它还没有,再添加一个(2)。问题是我得到了一个错误:
“无法同时更新“标记”和“标记”
这基本上意味着我不能同时做pull和addtoset。我还有别的办法吗
当然,我可以记住元素的所有ID,然后删除标记并添加到单独的查询中,但这听起来不太好。错误几乎就是它的意思,因为您不能在同一个更新操作中对相同“路径”的两个对象执行操作。您正在使用的两个运算符并不像您认为的那样按顺序处理 您可以使用“顺序”或其他形式的“批量”更新来实现这一点。当然,这是合理的,反过来也是合理的:
var bulk=db.coll.initializeOrderedBulkOp();
bulk.find({“tags”:1}).updateOne({“$addToSet”:{“tags”:2});
bulk.find({“tags”:1}).updateOne({“$pull”:{“tags”:1}});
bulk.execute();
这并不能保证其他任何东西都不会尝试修改,但它与您当前得到的最接近
还可以查看包含多个文档的原始文档。如果同时删除和添加文档,则可能是对“地图”建模,而不是对“集合”建模。如果是这样的话,一个对象的工作量可能比一个数组小 而不是将数据作为数组:
{ _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' } }
);
努力完成此答案。如果需要将数组中的一个值替换为另一个值,请检查此答案:
从
Mongo4.4
开始,聚合操作符允许应用自定义javascript函数来实现MongoDB查询语言不支持的行为
再加上在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 ] }
$function
采用3个参数:
,它是要应用的函数,其参数是要修改的数组。这里的功能只是将body
推送
ing
到数组中,然后2
过滤
ing
1
,其中包含args
函数体作为参数的记录字段。在我们的例子中,
“$tag”
,这是编写lang
函数体的语言。目前只有
可用js