首頁  >  文章  >  後端開發  >  聚合,將一個集合中的資料插入到另一個集合中

聚合,將一個集合中的資料插入到另一個集合中

王林
王林轉載
2024-02-10 23:30:19679瀏覽

聚合,將一個集合中的資料插入到另一個集合中

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 遊樂場

這裡有一個 mongo playground$merge 進行更新到一個集合。

以上是聚合,將一個集合中的資料插入到另一個集合中的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除