英文:
Limit the selection of data (the last document for each ID searched for) from the collection
问题
我正在尝试为每个聊天室获取最近用户消息的数组。但是在我的版本中,我只得到了一个包含所有聊天中发送的消息的数组。
func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {
if len(chatIds) == 0 {
return nil, nil
}
query := bson.M{"chat_id": bson.M{"$in": chatIds}}
cursor, err := r.colMessage.Find(ctx, query, nil)
if err != nil {
return nil, err
}
var messages []*Message
if err = cursor.All(ctx, &messages); err != nil {
return nil, err
}
err = cursor.Close(ctx)
if err != nil {
return nil, ErrInternal
}
return messages, err
}
有没有办法过滤样本,以便我只获取每个聊天的最后一条消息?
并且
也许你应该使用聚合来实现这样的目的?如果是这样,是循环使用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.
func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {
if len(chatIds) == 0 {
return nil, nil
}
query := bson.M{"chat_id": bson.M{"$in": chatIds}}
cursor, err := r.colMessage.Find(ctx, query, nil)
if err != nil {
return nil, err
}
var messages []*Message
if err = cursor.All(ctx, &messages); err != nil {
return nil, err
}
err = cursor.Close(ctx)
if err != nil {
return nil, ErrInternal
}
return messages, err
}
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
-
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
-
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论