mongodb 将数据从一个集合插入到另一个集合的聚合

soat7uwm  于 2023-01-25  发布在  Go
关注(0)|答案(1)|浏览(215)

我尝试执行以下操作,从特定用户的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"`
    ...
}

P.S. 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数组,对于每个聊天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
        },
    ]
}
oymdgrw7

oymdgrw71#

您可以简单地在$lookup的子管道中执行$sort + $limit方法。执行$unwind以将查找结果转换到last_message字段。最后,执行$merge以更新回chat集合。

db.chat.aggregate([
  {
    $lookup: {
      from: "message",
      localField: "id",
      foreignField: "chat_id",
      pipeline: [
        {
          $sort: {
            created: -1
          }
        },
        {
          $limit: 1
        }
      ],
      as: "last_message"
    }
  },
  {
    "$unwind": {
      path: "$last_message",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    "$merge": {
      "into": "chat",
      "on": "_id",
      "whenMatched": "merge"
    }
  }
])

Mongo Playground

相关问题