Элементы запроса MongoDB, которые находятся в массиве - PullRequest
1 голос
/ 02 мая 2020

Я работаю в интерфейсе mongoDB + (с express и mon goose) API.

У меня есть документ с более или менее такой структурой:

// npcs
{
   "_id" : ObjectId("5ea6c0f88e8ecfd3cdc39eae"),
    "flavor" : {
        "gender" : "...",
        "description" : "...",
        "imageUrl" : "...",
        "class" : "...",
        "campaign" : [ 
            {
                "campaignId" : "5eac9dfe8e8ecfd3cdc41aa0",
                "unlocked" : true
            }
        ]
    },
},
// ...

И второй документ в отдельной таблице, который выглядит следующим образом:

// user
{
"_id" : ObjectId("5e987f8e4b88382a98c84042"),
    "username" : "KuluGary",
    "campaigns" : [ 
        "5eac9dfe8e8ecfd3cdc41aa0", 
        "5eac9e458e8ecfd3cdc41ac1", 
        "5eac9e978e8ecfd3cdc41adb", 
        "5eac9eae8e8ecfd3cdc41ae3"
    ]    
}

Я хочу сделать запрос, в котором я получаю все NPC, которые являются частью кампании, частью которой является пользователь. и разблокированы. Вторая часть довольно проста, просто подумал, как только я получу NPC, чтобы отфильтровать тех, у кого есть unclocked false, но мне трудно визуализировать запрос, потому что я довольно незнаком с синтаксисом и использованием mongoDB.

Любая помощь будет принята с благодарностью.

1 Ответ

1 голос
/ 02 мая 2020

Я понимаю, что вы хотите "присоединиться" к пользователю со всеми соответствующими NP C?

Простое агрегирование с $ lookup будет работать:

db.userCollection.aggregate([
    {
        $match: {
            // match relevant users with whatever condition you want
        }
    },
    {
        $lookup: {
            from: "npc_collection",
            let: {campaigns: "$campaigns"},
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $gt: [
                                {
                                    $size: {
                                        $filter: {
                                            input: "$flavor.campaign",
                                            as: "campaign",
                                            cond: {
                                                $and: [
                                                    {$setIsSubset: ["$flavor.campaign.campaignId", "$$campaigns"]},
                                                    {$eq: ["$$campaign.unlocked", true]}
                                                ]
                                            }
                                        }
                                    }
                                },
                                0
                            ]
                        }
                    }
                }
            ],
            as: "relevant_npcs"
        }
    }
])

Обратите внимание, что из-за того, что NP C должен быть активным в определенной c кампании, а не просто разблокирован в любой, мы требуем использования $filter.

. если вы хотите искать только одного пользователя, вы делите это на 2 вызова, так как я считаю, что использование $ elemMatch даст лучшую производительность:

let campaigns = await db.userCollection.distinct("campaigns", {_id: userId})
let results = await db.npcCollection.find({"flavor.campaign": {$elemMatch: { campaignId: {$in: campaigns}, unlocked: true}}})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...