【问题标题】:MongoDB - Adding to a set and incrementingMongoDB - 添加到集合并递增
【发布时间】:2011-10-26 15:23:27
【问题描述】:

我正在尝试使用 MongoDB 计算单词使用量。我的收藏目前如下所示:

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

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

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

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

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

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

非常感谢一些帮助:)

【问题讨论】:

    标签: mongodb


    【解决方案1】:

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

    来自docs:“$inc ...如果对象中存在字段,则将字段增加数字值,否则将字段设置为数字值。”

    { $inc : { field : value } }
    

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

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

    到:

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

    您可以将操作 update 用于:

    { $inc: { 'words.foo': 1 } }
    

    如果 'foo' 不存在,则创建 { 'foo': 1 },否则递增 foo。

    例如:

    $ 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   }   }
    ]
    

    【讨论】:

    • 这仅适用于每个单词,并且无法对单词本身进行任何查询。我对这比专用的每个单词计数器元组更好的方式有点困惑。它也伴随着我在回答中提到的问题。
    • 用户可以输入整个单词数组(更改为word: 1 dict 形式),单词键要么添加为“1”,要么递增。因此,这正是问题所要求的:“我将所有新单词提取到一个数组中,但我试图找出 upsert 到单词数组并在单词已经存在时增加计数。” -- 全部在一个原子(更新)操作中完成,它更接近问题的原始结构(对或错)。
    • 很公平。我仍然认为这是该问题的次优解决方案。
    【解决方案2】:

    很遗憾,您的架构无法在一次更新中完成此操作。您的架构有点可疑,可能应该转换为具有单词计数器的专用集合,例如:

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

    这样可以避免很多问题,例如:

    • 达到最大文档大小限制
    • 当您增加文档大小时,强制 mongo 继续移动文档

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-26
      • 1970-01-01
      • 1970-01-01
      • 2019-02-24
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      相关资源
      最近更新 更多