我的收藏品看起来像这样。文档包含suggestions
数组。每个建议都可以有一个emotes
数组。用户每个建议只能表现一次。请注意,文档可以有多个建议
{
id: 1,
suggestions:[
{
id: 463,
emotes:[
{
id: 35,
userId: 2
},
{
id: 23,
userId: 3
},
]
},
...
]
},
...
emotes
只能包含userId
的1个实例。在推送新的表情元素之前,我需要检查userId
中是否存在emotes
。
我尝试过的解决方案:
(我使用更新命令语法来访问MongoDB 3.6功能。)
首次尝试:
addToSet
无效,因为emote
数组元素由userId
键入,而不是整个对象。
db.get().command({
update: 'channels',
updates:[
{
q:{
channelId,
"suggestions.id": suggestionOid,
},
u:{
$addToSet:
{
"suggestions.$[s].emotes": data
}
},
arrayFilters:[
{ 's.id': suggestionOid }
]
}
]
})
第二次尝试:
以下不起作用。用户可能已经有另一个建议的表情,这将导致$ne
查询条件失败。这意味着用户每个文档只能表示一个建议,他们应该能够表达对文档的所有建议。
db.get().command({
update: 'channels',
updates:[
{
q:{
channelId,
'suggestions.emotes.userId': {$ne: userId },
"suggestions.id": suggestionOid,
},
u:{
$push:
{
"suggestions.$[s].emotes": data
}
},
arrayFilters:[
{ 's.id': suggestionOid }
]
}
]
})
我愿意将emotes
移动到新的集合或更改其结构,如果这样可以使事情变得更容易。我无法改变其他任何事情。
答案 0 :(得分:0)
我使用$elemMatch
运算符解决了这个问题。
return channels.updateOne(
{
channelId,
"suggestions":{
$elemMatch:{
id: suggestionOid,
'emotes.user': {$ne: user }
}
},
},
{
$push:
{
"suggestions.$.emotes": data
}
}
)
来自mongodb docs的重要部分 https://docs.mongodb.com/manual/reference/operator/update/positional/
如果查询使用否定运算符(例如$ ne)匹配数组, $ not或$ nin,那么你不能使用位置运算符来更新 这个数组的值。
但是,如果查询的否定部分位于 $ elemMatch表达式,然后你可以使用位置运算符来 更新此字段。