我正在try 查找所有未读消息,通过聊天ID和用户ID.未读消息是如果chats_users.max_read_date小于message.create_date,message.from_id不等于用户.

它现在是如何运作的.我有一个聊天ID数组,我按chat_iduser_id搜索所有的Chats_USERS文档,然后循环搜索消息.

我想将其全部重写为一个查询,但我遇到了一些问题.我的问题是什么?我如何通过聊天ID和用户ID找到全部chats_users条消息,然后找到非用户写的所有消息,并且创建日期message.create_date大于chats_users.max_read_date

如何创建一个条件,以便对于每个聊天,找到它的Chats_USERS,然后只 Select 那些不是由发出请求的用户和所有其他聊天者写的消息,并且消息message.create_date的创建日期大于chats_users.max_read_date

消息收集

type ChatsUsers struct {
    ID     string `json:"id" bson:"id"`
    ChatID string `json:"chat_id" bson:"chat_id"`
    // user ID, which corresponds to the user ID in the system.
    UserID string `json:"user_id" bson:"user_id"`
    // MaxReadDate time of the last message read
    MaxReadDate int64 `json:"max_read_date" bson:"max_read_date"`
}

ChatsUser集合

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"`
}
Rewrite the query to get a single aggregation, the purpose of the query is to find all messages, by all chats that are unread and unscripted by a non-user, the uid variable is the user looking for such messages

fun (r *Mongo) UnreadMessageCount(ctx context.Context, chats []*Chat, uid string) (map[string]int64, error) {

    match := bson.A{}
    for _, chat := range chats {
        match = append(match, chat.ID)
    }

    chatsUsersList := make([]*domain.ChatsUsers, 0)
    for _, ch := range chats {
        chu, err := r.FindChatUser(ctx, ch.ID, uid)
        if err != nil {
            l.Error().Err(err).Msg("failed to find chat user")
            return nil, err
        }
        chatsUsersList = append(chatsUsersList, chu)
    }

    list := make([]*domain.Message, 0)

    for _, ch := range chats {
        for _, chu := range chatsUsersList {
            if chu.ChatID == ch.ID {
                filter := bson.D{
                    // search for messages by active chat IDs
                    { Key: "chat_id", Value: ch.ID},
                    // add filtering: that the message has not yet been read,
                    // and that the messages we select are not written by the current user.
                    {Key: "$and",
                        Value: bson.A{
                            bson.D{
                                {
                                    Key: "create_date", Value: bson.D{ bson.D{
                                    // $gt Matches values that are greater than the specified value.
                                    { Key: "$gt", Value: chu.MaxReadDate}}
                                },
                                // $ne Matches all values that are not equal to the specified value.
                                // https://www.mongodb.com/docs/manual/reference/operator/query-comparison/
                                {Key: "from_id", Value: bson.M{"$ne": uid}}
                            },
                        },
                    },
                }

                cursor, err := r.colMessage.Find(ctx, filter)
                ....

                var res []*domain.Message
                ....
            }
        }
    }

    // it doesn't make sense to use an array of messages, we need to create a map,
    // which will have the chat ID and the number of unread messages in it.
    messages := make(map[string]int64)
    for _, msg := range list {
        messages[msg.ChatID]++
    }

    return messages, nil
}

我的try (抱歉,这是一个非常不正确的查询,但我仍在try 编写正确的查询)

db.message.aggregate([
    {
        $match: {
            $expr: {
                $and: [
                    {
                        chat_id: {
                            $in: ["ad0a3405-1a16-48f9-93e6-51b17a7283e2"]
                        }
                    },
                    {
                        from_id: {
                            $ne: "63f5002735bb916dab3f2b1d"
                        }
                    },
                    {
                        $gt: ["$create_date", { $max: "$chats_users.max_read_date" }]
                    }
                ]
            }
        }
    },
    {
        $lookup: {
            from: "chatsusers",
            localField: "chat_id",
            foreignField: "chat_id",
            as: "chats_users"
        }
    },
    {
        $unwind: "$chats_users"
    },
    {
        $group: {
            _id: "$chat_id",
            messages: {
                $push: {
                    id: "$id",
                    chat_id: "$chat_id",
                    from_id: "$from_id",
                    create_date: "$create_date",
                    type: "$type",
                    media: "$media",
                    body: "$body",
                    update_at: "$update_at",
                    modifications: "$modifications",
                    viewed: "$viewed"
                }
            },
            max_read_date: { $max: "$chats_users.max_read_date" }
        }
    }
]);

在响应中,我只希望从测试数据中获得四个对象

{
      "_id": {
        "$oid": "63f502d3c1be2b78aaa6152e"
      },
      "body": "полковник конь тобі копитом в грудь! 3",
      "chat_id": "ad0a3405-1a16-48f9-93e6-51b17a7283e2",
      "create_date": 1677001427977,
      "from_id": "63f5002735bb916dab3f2b1d5g",
      "id": "G30uZ1HvlYQCZVwRRTBi",
      "media": "",
      "modifications": null,
      "type": "text",
      "update_at": 0,
      "viewed": false
    },
    {
      "_id": {
        "$oid": "63f502d2c1be2b78aaa6152d"
      },
      "body": "полковник конь тобі копитом в грудь! 2",
      "chat_id": "ad0a3405-1a16-48f9-93e6-51b17a7283e2",
      "create_date": 1677001428101,
      "from_id": "63f5002735bb916dab3f2b1d5g",
      "id": "RzrfvZuLWyhrKOHEx5gK",
      "media": "",
      "modifications": null,
      "type": "text",
      "update_at": 0,
      "viewed": false
    },

    {
      "_id": {"$oid": "63f5002735bb916dab3f2bb2"},
      "body": "after you",
      "chat_id": "ad0a3405-1a16-48f9-93e6-51b17a7283e2-y7y3r2",
      "create_date": 1677001427398,
      "from_id": "63f5002735bb916dab3f2b23",
      "id": "e5189d64-0c43-41dd-befa-f554d09475cf",
      "media": "",
      "modifications": null,
      "type": "text",
      "update_at": 0,
      "viewed": true
    },
    {
      "_id": {"$oid": "63f5002735bb916dab3f2bb1"},
      "body": "I'm not religious",
      "chat_id": "ad0a3405-1a16-48f9-93e6-51b17a7283e2-y7y3r2",
      "create_date": 1677001427327,
      "from_id": "63f5002735bb916dab3f2b23",
      "id": "a1fbc6b0-5f8d-4fa2-aef7-807314dfba0d",
      "media": "",
      "modifications": null,
      "type": "text",
      "update_at": 0,
      "viewed": true
    }

Test data

我的第二次try

db.chats_users.aggregate([
    {
        $match: {
            user_id: "63f5002735bb916dab3f2b1d",
            chat_id: { $in: ["ad0a3405-1a16-48f9-93e6-51b17a7283e2"] },
        }
    },
    {
        $lookup: {
            from: "message",
            let: { chat_id: "$chat_id", max_read_date: "$max_read_date" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: ["$chat_id", "$$chat_id"] },
                                { $ne: ["$from_id", "63f5002735bb916dab3f2b1d"] },
                                { $gt: ["$create_date", "$$max_read_date"] },
                            ]
                        }
                    }
                }
            ],
            as: "messages"
        }
    },
    {
        $project: {
            chat_id: 1,
            message_count: { $size: "$messages" }
        }
    }
])

推荐答案

事实证明,它更简单,我使用chatsusers集合进行了查询-这简化了查询.

db.chatsusers.aggregate([
    {
        $match: {
            chat_id: {
                $in: ["ad0a3405-1a16-48f9-93e6-51b17a7283e2", "22e1e6f1-459a-4ed1-bc8f-c9947492972d"],
            },
        }
    },
    {
        $lookup: {
            from: "message",
            localField: "chat_id",
            foreignField: "chat_id",
            let: { chat_id: "$chat_id", max_read_date: "$max_read_date" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: ["$chat_id", "$$chat_id"] },
                                { $ne: ["$from_id", "63f5002735bb916dab3f2b1e"] },
                                { $gt: ["$create_date", "$$max_read_date"] },
                            ]
                        }
                    },
                }
            ],
            as: "messages"
        }
    },
    {
        $project: {
            chat_id: 1,
            message_count: { $size: "$messages" },
        }
    },
    {
        $group: {
            _id: "$chat_id",
            message_count: { $sum: "$message_count" },
        },
    },
    {
        $sort: { "message_count": -1 },
    },
    {
        $project: {
            _id: 0,
            chat_id: "$_id",
            message_count: 1,
        },
    },
])

Playground

Mongodb相关问答推荐

如何在MongoDB中查找和过滤嵌套数组

在单个mongo文档中组合数组与聚合

如何在MongoDB中使用Aggregation来计算两个键相同但字段不同的对象数组的总值,并将其合并为一个?

数组中字符串的Mongo查询集合和推送到新数组嵌套对象

如何在 mongodb 中将一个方面的结果合并到一个有条件的列表中?

使用 mongo-driver/mongo 使用键/值对中的值表达式查找文档

通过insertId MongoDB获取文档

Mongoose 更新不同类型的记录

MongoDB 将 JSON 字符串转换为数组[{obj1},{obj2}]的实际对象

mongo shell 命令不接受使用 db 命令

在 mongodb 聚合中的阶段之后输出具有序列数字 id 的新集合

mongoose中的 required是什么意思?

使用 MongoDB C# 驱动程序在嵌套数组上使用过滤器生成器进行查询

MongoDB:自动生成的 ID 为零

有没有办法自动更新 MongoDB 中的两个集合?

MongoDB 日志(log)文件和 oplog 有何不同?

直接从 URL 查询字符串提供的 mongo 查询有多危险?

mongodb启动错误

错误:需要数据和盐参数

MongoDB 用 $type 匹配一个数组?