你可以在 Mongo 中为 $addToSet 指定一个键吗?
Posted
技术标签:
【中文标题】你可以在 Mongo 中为 $addToSet 指定一个键吗?【英文标题】:Can you specify a key for $addToSet in Mongo? 【发布时间】:2013-01-09 18:45:06 【问题描述】:我有一份文件:
'profile_set' :
[
'name' : 'nick', 'options' : 0 ,
'name' : 'joe', 'options' : 2 ,
'name' : 'burt', 'options' : 1
]
如果名称尚不存在(无论选项如何),并且希望将新文档添加到 profile_set
集中。
所以在这个例子中,如果我尝试添加:
'name' : 'matt', 'options' : 0
它应该添加它,但是添加
'name' : 'nick', 'options' : 2
不应执行任何操作,因为名称为 nick
的文档已经存在,即使 option
不同。
Mongo 似乎与整个元素匹配,我最终检查它是否相同,我最终得到
profile_set containing ['name' : 'nick', 'options' : 0, 'name' : 'nick', 'options' : 2]
有没有办法用$addToSet
做到这一点,还是我必须推送另一个命令?
【问题讨论】:
由于您不能保证 $addToSet 会首先运行,您需要两个命令来执行此操作 【参考方案1】:如果name
已存在于profile_set
中,您可以使用阻止更新的查询对象限定您的update
。在外壳中:
db.coll.update(
_id: id, 'profile_set.name': $ne: 'nick',
$push: profile_set: 'name': 'nick', 'options': 2)
因此,这只会对具有匹配 _id
并且没有 profile_set
元素(其中 name
是 'nick'
)的文档执行 $push
。
【讨论】:
如果我以后需要更改 mick 的名称,即更改现有的数组对象,而不是添加新的。有没有办法在一个原子更新操作中仍然遵守名称的唯一约束? 关于更改 profile_set 中现有对象的后续问题:***.com/questions/26590219/…。 无论我去哪里解决 mongoose 或 mongo 问题,@JohnnyHK 总是救了我。 @JohnnyHK 如果我需要覆盖已经存在的值怎么办? 请任何人回复上述@Alex 问题。如果元素已经存在 else 推送,需要更新元素吗?【参考方案2】:从 MongoDB 4.2 开始,有一种方法可以使用 aggregation expressions in update。
对于您的示例,您可以这样做:
newSubDocs = [ 'name' : 'matt', 'options' : 0, 'name' : 'nick', 'options' : 2 ];
db.coll.update( _id:1 ,
[
$set: profile_set: $concatArrays: [
"$profile_set",
$filter:
input:newSubDocs,
cond: $not: $in: [ "$$this.name", "$profile_set.name" ]
]
])
【讨论】:
MongoError: '0.$set' 中的美元 ($) 前缀字段 '$set' 对存储无效。 听起来你没有得到正确的完整语法。您可能想在 community.mongodb.com 中询问所有详细信息以上是关于你可以在 Mongo 中为 $addToSet 指定一个键吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python 中为递归对象创建 Mongo 文档模式?