限制从集合中选择数据(搜索的每个ID的最后一个文档)。

huangapple go评论121阅读模式
英文:

Limit the selection of data (the last document for each ID searched for) from the collection

问题

我正在尝试为每个聊天室获取最近用户消息的数组。但是在我的版本中,我只得到了一个包含所有聊天中发送的消息的数组。

  1. func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {
  2. if len(chatIds) == 0 {
  3. return nil, nil
  4. }
  5. query := bson.M{"chat_id": bson.M{"$in": chatIds}}
  6. cursor, err := r.colMessage.Find(ctx, query, nil)
  7. if err != nil {
  8. return nil, err
  9. }
  10. var messages []*Message
  11. if err = cursor.All(ctx, &messages); err != nil {
  12. return nil, err
  13. }
  14. err = cursor.Close(ctx)
  15. if err != nil {
  16. return nil, ErrInternal
  17. }
  18. return messages, err
  19. }

有没有办法过滤样本,以便我只获取每个聊天的最后一条消息?

并且

也许你应该使用聚合来实现这样的目的?如果是这样,是循环使用Find还是使用聚合更好?

英文:

I'm trying to get an array of recent user messages for each chat room. But in my version I get just an array of messages that have been sent for all the chats.

  1. func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {
  2. if len(chatIds) == 0 {
  3. return nil, nil
  4. }
  5. query := bson.M{"chat_id": bson.M{"$in": chatIds}}
  6. cursor, err := r.colMessage.Find(ctx, query, nil)
  7. if err != nil {
  8. return nil, err
  9. }
  10. var messages []*Message
  11. if err = cursor.All(ctx, &messages); err != nil {
  12. return nil, err
  13. }
  14. err = cursor.Close(ctx)
  15. if err != nil {
  16. return nil, ErrInternal
  17. }
  18. return messages, err
  19. }

Is there any way I can filter the sample so that I get only one last message for each chat?

And

Perhaps you should use aggregations for such purposes? If so, is it better to cycle Find or use aggregations?

答案1

得分: 1

假设你所说的“最后一个”是指具有最近时间戳的那个,我可以想到两种方法来实现。

如果chat_id和timestamp上都有索引,两种方法都会表现得更好。

1)找到匹配单个chat_id的记录,按照时间戳降序排序,并限制返回结果为1条。这样只需要加载所需的文档,返回的扫描比例为1:1。对于每个chat重复此操作。

2)使用聚合操作一次匹配一个chats数组,按照时间戳排序,然后按chat_id分组,只选择每个组中的第一条消息。这样需要加载每个chat的许多消息。然而,这种方法将在单个操作和单个网络往返中返回所有文档。

哪种方法更好取决于以下因素:

  • 网络往返的开销有多大
  • 由于扫描所有额外文档的资源开销,会有多少延迟
  • 查询的频率有多高
  • 同时运行查询的实例数量有多少
英文:

Assuming that by "last" you mean the one with the most recent timestamp, I can think of 2 ways to do it.

Both will perform better if there is an index on chat_id:1, timestamp:1

  1. Find matching a single chat_it, sort by timestamp descending, with a limit of 1. This would require loading only the desired document, for a 1:1 scanned returned ratio. Repeat for each chat

  2. Aggregation to match an array ofchats at once, sort by timestamp, and then group by chat_id selecting only the first message from each. This would require loading many messages from each chat. However, this method would return all of the documents in a single operation with a single network round trip.

Which method is better for you would depend on:

  • how expensive is the network round trip
  • how much delay will there be due to the resource overhead of scanning all of the extra documents
  • how often the query will run
  • how many instances of the query will be run simultaneously

huangapple
  • 本文由 发表于 2022年12月28日 20:57:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/74940548.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定