Как сопоставить, найти и спроектировать с фильтрацией по другой таблице в MongoDB? - PullRequest
0 голосов
/ 14 февраля 2020

Моя цель - получить список активных предупреждений и соответствующих дат чтения для данного пользователя.

У меня есть alerts коллекция

{
    "id" : "id",
    "field1": 1,
    "field2": 1,
    "field3": 1,
    "field4": 1,
    "status" : { "name": "ACTIVE" }
}

Я отслеживаю, когда пользователь прочитал предупреждение, используя alertstracking collection

{ 
    "alertid" : "alertidvalue", 
    "userid" : "useridvalue", 
    "id" : "id", 
    "readdate" : ISODate("2020-02-14T00:45:45.959+0000")
}

Это рабочий запрос, который у меня есть, но мне было интересно, есть ли лучшие / более быстрые способы сделать это. Я собирался проиндексировать поля alerttid, userid в коллекции alertstracking.

db.getCollection("alerts").aggregate([
    {
        $match: {
            "status.name": "ACTIVE"
        }
    },
    {
        $lookup: {
            from: "alertstracking",
            localField: "id",
            foreignField: "alertid",
            as: "alerttrack"
        }
    },
    {
        $project: {
            "id": 1,
            "field1": 1,
            "field2": 1,
            "field3": 1,
            "field4": 1,
            "useralerttrack": {
                $filter: {
                    input: "$alerttrack",
                    as: "track",
                    cond: {
                        $eq: ["$$track.userid", "useridvalue"]
                    }
                }
            }
        }
    },
    {
        $project: {
            "id": 1,
            "field1": 1,
            "field2": 1,
            "field3": 1,
            "field4": 1,
            "readdate": {
                $arrayElemAt: ["$useralerttrack.readdate", 0]
            }
        }
    }
])

Я надеюсь не использовать $project дважды и повторять нужные мне поля. Я должен был сделать это, чтобы получить доступ к useralerttrack.

1 Ответ

0 голосов
/ 14 февраля 2020

Вы можете попробовать это так:

 db.getCollection("alerts").aggregate([
    {
        $match: {
            "status.name": "ACTIVE"
        }
    },
    {
        $lookup:
        {
            from: "alertstracking",
            let: { id: "$id" },
            pipeline: [
                {
                    $match:
                    {
                        $expr:
                        {
                            $and:
                                [
                                    { $eq: ["$alertid", "$$id"] },
                                    { $eq: ["$userid", "useridvalue"] }
                                ]
                        }
                    }
                }, { $project: { _id: 0, readdate: 1 } }
            ],
            as: "readdate"
        }
    }, {
        $addFields: {
            readdate: {
                $arrayElemAt: ["$readdate.readdate", 0]
            }
        }
    }
])

Тест: MongoDB-Playground

...