php小編柚子在這篇文章中將為大家介紹一個常見的操作-聚合,即將一個集合中的資料插入到另一個集合中。聚合操作在程式設計中非常常見,可以用於合併資料、去重、篩選等多種場景。透過聚合操作,我們可以輕鬆地對資料進行處理和管理,提高程式碼的效率和可讀性。接下來,我們將詳細介紹聚合操作的使用方法及注意事項,幫助大家更能掌握這項技巧。
我正在嘗試執行以下操作,從特定用戶的chat
集合中獲取聊天列表,並將發送的message
集合中的最後一條訊息會新增到每個聊天的該清單中。
現在這是如何運作的,我有兩種方法,如下所述
首先,我只是使用聊天成員 id 獲取聊天列表,第二種方法使用聚合來查找每個聊天的最後一條訊息,然後我只需將訊息與聊天 id 進行匹配
收藏聊天:
type chat struct { id string `json:"id" bson:"id"` participants []string `json:"participants" bson:"participants"` lastmessage *message `json:"last_message,omitempty" bson:"last_message"` ... }
附註
lastmessage
- 始終為零,我只需要它來為使用者編寫回應。
集合message
:
type message struct { id string `json:"id" bson:"id"` chatid string `json:"chat_id" bson:"chat_id"` fromid string `json:"from_id" bson:"from_id"` createdate int64 `json:"create_date" bson:"create_date"` body string `json:"body" bson:"body"` updateat int64 `json:"update_at" bson:"update_at"` ... }
第一種方法:我需要此方法來取得特定聊天參與者的活動聊天清單。
func activechats(ctx context.context, uid string) ([]*chat, error) { ... filter := bson.d{primitive.e{key: "participants", value: uid}} cursor, err := r.col.find(ctx, filter, nil) if err != nil {...} var ch []*chat if err = cursor.all(ctx, &ch); err != nil {...} if err = cursor.close(ctx); err != nil {...} ... }
第二種方法:我需要此方法來獲取每個聊天的最後一條訊息,輸入是一組聊天id,並且對於每個聊天,我都會搜尋最後一條訊息(如果有)。為此,我使用聚合。
func lastmessages(ctx context.context, chatids []string) (map[string]*message, error) { matchstage := bson.d{ primitive.e{ key: "$match", value: bson.d{ primitive.e{ key: "chat_id", value: bson.d{ primitive.e{key: "$in", value: chatids}, }, }, }, }} sortstage := bson.d{primitive.e{key: "$sort", value: bson.d{primitive.e{key: "created", value: -1}}}} groupstage := bson.d{primitive.e{ key: "$group", value: bson.d{ primitive.e{ key: "_id", value: bson.d{ primitive.e{key: "chat_id", value: "$chat_id"}, }, }, primitive.e{ key: "message", value: bson.d{ primitive.e{key: "$first", value: "$$root"}, }, }, }, }} cursor, err := r.colmessage.aggregate(ctx, mongo.pipeline{matchstage, groupstage, sortstage}) if err != nil {...} var res []*aggregationresultgenerated if err = cursor.all(ctx, &res); err != nil {...} ... }
我知道這是一個非常糟糕的解決方案,但這是我迄今為止所能想到的,非常遺憾(不工作)。我嘗試解決這個問題
db.chat.aggregate([ { $match: { participants: "participant_id", }, { $lookup: { from: "message", // other table name localfield: "id", // name of chat table field foreignfield: "chat_id", // name of message table field as: "msg", } }, { $unwind: "$msg", }, { $match: { chat_id : { $in: ["$$root._id"], }, }, }, { $sort: { "created": -1, }, }, { $group: { "_id": { "chat_id": "$chat_id" }, "doc": { "$last": "$$root" } } }, { $project: { last_message: "$msg", } } ])
我的問題是:如何使用聚合來獲取特定用戶的聊天列表,並為每個聊天從message
集合中添加物件chat
中字段last_message 中的最後一條訊息?
現在如何運作:
{ "chats": [ { "id": "4hWsHam3ZZpoyIw44q3D", "title": "Chat example", "create-date": 1674476855918, "participants": [ "63ce54460aeee5e72c778d90", "63ce54460aeee5e72c778d92" ], "owner_id": "63ce54460aeee5e72c778d90", "last_message": { "id": "tzwekCiCLSXJ4tfdQuHH", "chat_id": "4hWsHam3ZZpoyIw44q3D", "from_id": "63ce54460aeee5e72c778d92", "create_date": 1674557062031, "body": "text", "update_at": 0, "viewed": false }, "unread": 5 }, { "id": "Anjrr9RCWFzq030Cwz7S", "title": "New chat One", "create-date": 1674476909054, "participants": [ "63ce54460aeee5e72c778d90", "63ce54460aeee5e72c778d96" ], "owner_id": "63ce54460aeee5e72c778d90", "last_message": { "id": "7YqhhS1-EfMRSZtGCH0Z", "chat_id": "Anjrr9RCWFzq030Cwz7S", "from_id": "63ce54460aeee5e72c778d96", "create_date": 1674575017115, "body": "text", "update_at": 0, }, "unread": 1 }, ] }
編輯:正如op在評論中提到的,update/$merge
到集合是沒有必要的。
您可以簡單地在 $lookup
的子管道中執行 $sort
$limit
方法。執行 $unwind
將查找結果寫入 last_message
欄位。最後,執行 $merge
以更新回 chat
集合。
db.chat.aggregate([ { $match: { participants: "63ce54460aeee5e72c778d90", } }, { $lookup: { from: "message", localField: "id", foreignField: "chat_id", pipeline: [ { $sort: { created: -1 } }, { $limit: 1 } ], as: "last_message", } }, { $unwind: { path: "$last_message", preserveNullAndEmptyArrays: true } }, { $project: { last_message: "$last_message" } } ])
這裡有一個舊 mongo playground 與 $merge
進行更新到一個集合。
以上是聚合,將一個集合中的資料插入到另一個集合中的詳細內容。更多資訊請關注PHP中文網其他相關文章!