MongoDB - 添加到集合和递增

时间:2011-10-26 15:23:27

标签: mongodb

我正在尝试使用MongoDB统计单词使用情况。我的收藏目前看起来像这样:

{'_id':###, 'username':'Foo', words:[{'word':'foo', 'count':1}, {'word':'bar', 'count':1}]}

当发布一个新帖子时,我将所有新单词提取到一个数组中,但我试图想要插入单词数组并在该单词已经存在的情况下递增计数。

在上面的示例中,例如,如果用户“Foo”发布了“lorem ipsum foo”,我会将“lorem”和“ipsum”添加到用户单词数组中,但会增加“foo”的计数。 / p>

这可以在一个查询中使用吗?目前我正在使用addToSet:

'$addToSet':{'words':{'$each':word_array}}

但这似乎没有提供任何增加字数的方法。

非常感谢一些帮助:)

2 个答案:

答案 0 :(得分:9)

如果您愿意从列表切换到哈希(对象),则可以原子地执行此操作。

docs:“$inc ...增量字段中的数字值if字段存在于对象中,否则将字段设置为数字值。”

{ $inc : { field : value } }

所以,如果你能重构你的容器和对象:

words: [
  {
    'word': 'foo',
    'count': 1
  },
  ...
]

为:

words: {
  'foo': 1,
  'other_word: 2,
  ...
}

您可以将操作update用于:

{ $inc: { 'words.foo': 1 } }
如果'foo'不存在,

将创建{ 'foo': 1 },否则增加foo。

E.g:

$ db.bar.insert({ id: 1, words: {} });
$ db.bar.find({ id: 1 })
[ 
  {   ...,   "words" : {     },   "id" : 1   }
]
$ db.bar.update({ id: 1 }, { $inc: { 'words.foo': 1 } });
$ db.bar.find({ id: 1 })
[ 
  {   ...,   "id" : 1,   "words" : {   "foo" : 1   }   }
]
$ db.bar.update({ id: 1 }, { $inc: { 'words.foo': 1 } });
$ db.bar.find({ id: 1 })
[ 
  {   ...,   "id" : 1,   "words" : {   "foo" : 2   }   }
]

答案 1 :(得分:2)

不幸的是,在使用您的架构的单个更新中无法执行此操作。您的架构有点可疑,应该转换为具有字计数器的专用集合,例如:

db.users {_id:###, username:'Foo'}
db.words.counters {_id:###, word:'Word', userId: ###, count: 1}

这将避免很多问题,例如:

  • 达到最大文档大小限制
  • 强制mongo在增加文件大小时继续移动文件

这两种方案都需要两次更新来执行您想要的操作,这会引入原子性问题。通过循环遍历word_array来更新每个单词更好,更安全(并且可以使用两种解决方案)。