Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Agregasi, memasukkan data dari satu koleksi ke koleksi lain

Agregasi, memasukkan data dari satu koleksi ke koleksi lain

王林
王林ke hadapan
2024-02-10 23:30:19679semak imbas

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"`
    ...
}

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
        },
    ]
}

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"
    }
  }
])

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!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam