Dalam artikel ini, editor PHP Youzi akan memperkenalkan anda kepada operasi biasa - pengagregatan, iaitu memasukkan data dalam satu koleksi ke koleksi lain. Operasi pengagregatan adalah sangat biasa dalam pengaturcaraan dan boleh digunakan dalam pelbagai senario seperti penggabungan data, penyahduplikasian dan penapisan. Melalui operasi pengagregatan, kami boleh memproses dan mengurus data dengan mudah, meningkatkan kecekapan dan kebolehbacaan kod. Seterusnya, kami akan memperkenalkan penggunaan operasi pengagregatan dan langkah berjaga-jaga secara terperinci untuk membantu semua orang menguasai teknik ini dengan lebih baik.
Saya cuba melakukan perkara berikut untuk menambahkan mesej terakhir daripada koleksi chat
集合中获取聊天列表,并将发送的 message
pengguna tertentu pada senarai itu untuk setiap sembang.
Sekarang bagaimana ini berfungsi, saya mempunyai dua kaedah seperti yang diterangkan di bawah
Mula-mula saya hanya mendapat senarai sembang menggunakan id ahli sembang, kaedah kedua menggunakan pengagregatan untuk mencari mesej terakhir setiap sembang dan kemudian saya hanya memadankan mesej dengan id sembang
Sembang Kegemaran:
type chat struct { id string `json:"id" bson:"id"` participants []string `json:"participants" bson:"participants"` lastmessage *message `json:"last_message,omitempty" bson:"last_message"` ... }
P.S.
lastmessage
- sentiasa sifar, saya hanya memerlukannya untuk menulis respons untuk pengguna.
Koleksimessage
:
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"` ... }
Kaedah pertama: Saya memerlukan kaedah ini untuk mendapatkan senarai sembang aktif peserta sembang tertentu.
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 {...} ... }
Kaedah kedua: Saya memerlukan kaedah ini untuk mendapatkan mesej terakhir setiap sembang, input ialah set id sembang, dan untuk setiap sembang saya mencari mesej terakhir jika ada. Untuk ini saya menggunakan agregasi.
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 {...} ... }
Saya tahu ini adalah penyelesaian yang sangat buruk tetapi ini sahaja yang saya boleh fikirkan setakat ini dan ia sangat menyedihkan (tidak berfungsi). Saya cuba selesaikan masalah ini
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", } } ])
Soalan saya ialah: Bagaimana untuk menggunakan pengagregatan untuk mendapatkan senarai sembang untuk pengguna tertentu dan untuk setiap sembang tambahkan mesej terakhir dalam medan last_message dalam objek chat
daripada koleksi message
集合中添加对象 chat
?
Cara ia berfungsi sekarang:
{ "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 }, ] }
EDIT: Seperti yang dinyatakan OP dalam ulasan, kemas kini/$merge
kepada koleksi tidak perlu.
Anda hanya boleh melaksanakan kaedah $sort
+ $limit
dalam sub-pipeline $lookup
. Jalankan $unwind
untuk menulis hasil carian ke medan last_message
. Akhir sekali, laksanakan $lookup
的子管道中执行 $sort
+ $limit
方法。执行 $unwind
将查找结果写入 last_message
字段。最后,执行 $merge
以更新回 chat
untuk mengemas kini kembali kepada koleksi 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" } } ])
Ini adalah lama mongo taman permainan dengan $merge
dikemas kini menjadi koleksi.
Atas ialah kandungan terperinci Agregasi, memasukkan data dari satu koleksi ke koleksi lain. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!