MongoDB поиск, когда внешнее поле является массивом - PullRequest
0 голосов
/ 13 ноября 2018

Я искал в Интернете и StackOverflow, но не могу найти ответ или даже вопрос.

У меня есть две коллекции, reports и users. Я хочу, чтобы мой запрос возвратил все отчеты и указал, есть ли у указанного пользователя этот отчет в качестве избранного в их массиве.

Сборник отчетов

{ _id: 1, name:"Report One"}
{ _id: 2, name:"Report Two"}
{ _id: 3, name:"Report Three"}

Коллекция пользователей

{_id: 1, name:"Mike", favorites: [1,3]}
{_id: 2, name:"Tim", favorites: [2,3]}

Желаемый результат для users.name = "Mike"

{ _id: 1, name:"Report One", favorite: true}
{ _id: 2, name:"Report Two", favorite: false}
{ _id: 3, name:"Report Three", favorite: true}

Все ответы, которые я могу найти, используют $ unwind для локального (reports) поля, но в этом случае локальное поле не является массивом. Внешнее поле - это массив.

Как я могу раскрутить чужое поле? Есть ли лучший способ сделать это?

Я видел в Интернете, что кто-то предложил создать еще одну коллекцию favorites, которая будет содержать:

{ _id: 1, userId: 1, reportId: 1 }
{ _id: 2, userId: 1, reportId: 3 }
{ _id: 3, userId: 2, reportId: 2 }
{ _id: 4, userId: 2, reportId: 3 }

Похоже, этот метод должен быть необычным. Должно быть просто присоединиться к идентификатору во внешнем массиве, верно?

1 Ответ

0 голосов
/ 13 ноября 2018

Вы можете использовать $ lookup с пользовательским конвейером , который даст вам 0 или 1 результат, а затем использовать $ size для преобразования массива в одно логическое значение:

db.reports.aggregate([
    {
        $lookup: {
            from: "users",
            let: { report_id: "$_id" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: [ "$name", "Mike" ] },
                                { $in: [ "$$report_id", "$favorites" ] }
                            ]
                        }
                    }
                }
            ],
            as: "users"
        }
    },
    {
        $project: {
            _id: 1,
            name: 1,
            favorite: { $eq: [ { $size: "$users" }, 1 ] }
        }
    }
])

В качестве альтернативы, если вам нужно использовать версию MongoDB ниже 3.6, вы можете использовать обычный $lookup, а затем использовать $ filter , чтобы получить только тех пользователей, у которых name равно Mike:

db.reports.aggregate([
    {
        $lookup: {
            from: "users",
            localField: "_id",
            foreignField: "favorites",
            as: "users"
        }
    },
    {
        $project: {
            _id: 1,
            name: 1,
            favorite: { $eq: [ { $size: { $filter: { input: "$users", as: "u", cond: { $eq: [ "$$u.name", "Mike" ] } } } }, 1 ] }
        }
    }
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...