如何在mongodb中通过$ addToSet更新后设置数组长度?

时间:2011-09-07 09:48:37

标签: mongodb

文档结构如下所示,

{
    blacklists:[]         // elements should be unique
    blacklistsLength:0    // length of blacklists
}

blacklists添加值集很容易。

db.posts.update({_id:...}, {$addtoSet:{blacklists:{$each:['peter', 'bob', 'steven']}}});

但如何同时更新blacklistLength以反映更改?

4 个答案:

答案 0 :(得分:4)

这是不可能的。你要么

  1. 使用后续的findAndModify单独更新长度 命令或

  2. 您可以按名称执行此操作,并使用否定重写查询 你的标准和$ push而不是$ addToSet(不一定 自addToSet以来,大型黑名单所需的速度要快得多 无论索引如何,总是o(n):

    db.posts.update({_id:..., blacklists:{$ne:'peter'}}, {$push:{blacklists:{'peter'}},$inc:{blacklistsLength: 1}});
    
  3. 后者非常安全,因为列表和长度是原子调整的,但显然性能略有下降。由于大型阵列上的$ 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)