Agregasi, memasukkan data dari satu koleksi ke koleksi lain

王林
Lepaskan: 2024-02-10 23:30:19
ke hadapan
731 orang telah melayarinya

Agregasi, memasukkan data dari satu koleksi ke koleksi lain

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.

Kandungan soalan

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"`
    ...
}
Salin selepas log masuk

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"`
    ...
}
Salin selepas log masuk

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 {...}
    ...
}
Salin selepas log masuk

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 {...}
    ...
}
Salin selepas log masuk

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",
        }
    }
])
Salin selepas log masuk

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
        },
    ]
}
Salin selepas log masuk

Penyelesaian

EDIT: Seperti yang dinyatakan OP dalam ulasan, kemas kini/$mergekepada 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"
    }
  }
])
Salin selepas log masuk

taman permainan mongo

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!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan