MongoDB - 添加到集合并递增

发布于 2024-12-11 22:08:58 字数 471 浏览 0 评论 0原文

我正在尝试使用 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}}

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

非常感谢一些帮助:)

I am trying to count word usage using MongoDB. My collection currently looks like this:

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

When a new post is made, I extract all the new words to an array but I'm trying to figure out to upsert to the words array and increment the count if the word already exists.

In the example above, for example, if the user "Foo" posted "lorem ipsum foo", I'd add "lorem" and "ipsum" to the users words array but increment the count for "foo".

Is this possible in one query? Currently I am using addToSet:

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

But that doesn't seem to offer any way of increasing the words count.

Would very much appreciate some help :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇柔作态 2024-12-18 22:08:58

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

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

{ $inc : { field : value } }

因此,如果您可以将容器和对象重构为:

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

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

则可以使用操作 update with: ,

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

If you're willing to switch from a list to hash (object), you can atomically do this.

From the docs: "$inc ... increments field by the number value if field is present in the object, otherwise sets field to the number value."

{ $inc : { field : value } }

So, if you could refactor your container and object:

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

to:

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

you could use the operation update with:

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

which would create { 'foo': 1 } if 'foo' doesn't exist, else increment 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   }   }
]
眼眸里的快感 2024-12-18 22:08:58

不幸的是,不可能通过您的架构的一次更新来完成此操作。您的模式有点问题,可能应该转换为具有字计数器的专用集合,例如:

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

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

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

两种情况都需要两次更新才能完成您想要的操作,这会引入原子性问题。通过循环访问 word_array 来更新每个单词更好、更安全(并且这两种解决方案都是可能的)。

Unfortunately it is not possible to do this in a single update with your schema. Your schema is a bit questionable and should probably be converted to having a dedicated collection with word counters, e.g :

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

That will avoid quite a few issues such as :

  • Running into maximum document size limits
  • Forcing mongo to keep moving around your documents as you increase their size

Both scenarios require two updates to do what you want which introduces atomicity issues. Updating per word by looping through word_array is better and safer (and is possible with both solutions).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文