文档结构如下所示,
{
blacklists:[] // elements should be unique
blacklistsLength:0 // length of blacklists
}
向blacklists
添加值集很容易。
db.posts.update({_id:...}, {$addtoSet:{blacklists:{$each:['peter', 'bob', 'steven']}}});
但如何同时更新blacklistLength
以反映更改?
答案 0 :(得分:4)
这是不可能的。你要么
使用后续的findAndModify单独更新长度 命令或
您可以按名称执行此操作,并使用否定重写查询 你的标准和$ push而不是$ addToSet(不一定 自addToSet以来,大型黑名单所需的速度要快得多 无论索引如何,总是o(n):
db.posts.update({_id:..., blacklists:{$ne:'peter'}}, {$push:{blacklists:{'peter'}},$inc:{blacklistsLength: 1}});
后者非常安全,因为列表和长度是原子调整的,但显然性能略有下降。由于大型阵列上的$ push与$ addToSet性能问题,它还具有更好的整体性能的好处(并且黑名单往往变得庞大并且记住更新的$ push版本在更新标准中使用黑名单上的索引而$ addToSet在设置扫描期间不会使用索引)它通常是最好的解决方案。
答案 1 :(得分:1)
以下不起作用吗?
db.posts.update({_id:...}, {
$addtoSet:{blacklists:{$each:['peter', 'bob', 'steven']}},
$set: {blacklistsLength: ['peter', 'bob', 'steven'].length}
});
答案 2 :(得分:0)
我遇到了类似的问题,请参阅此处的讨论:google groups mongo
您可以注意到,在此讨论之后,一个错误已经打开: Mongo Jira
答案 3 :(得分:0)
当您将项目插入数据库时,只需查询该项目以查看它是否在您的嵌入式阵列中。这样,您就可以避免推送重复项目,并且只在添加新项目时递增计数器。
q = {'blacklists': {'$nin': ['blacklist_to_insert'] }}
u = {
'$push' : {'blacklists': { 'blacklist_to_insert' } },
'$inc' : {'total_blacklists': 1 }
}
o = { 'upsert' : true }
db.posts.update(q,u,o)