Запрос MongoDB двойной вложенный массив с соответствующими наборами

#mongodb #mongoose #mongodb-query

Вопрос:

Будучи не знаком с Монго и все еще прогрессируя, я столкнулся с проблемой, которую не могу решить (и я не знаю, возможно ли это).

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

 {
    "_id": "6138451fb3a7d9564a0229fd"
    "title": "Event  1",
    "cohortsGroups": [
        [
          {
            "_id": "6124beef59d728c82088fd59",
            "name": "2022",
            "type": "promotion"
          }, 
          {
            "_id": "6124bf2159d728c82088fd60",
            "name": "Toronto",
            "type": "city"
          }
       ],
       [
         {
            "_id": "6124beef59d728c82088fd57",
            "name": "2024",
            "type": "promotion"
          },
          {
            "_id": "6124bf2159d728c82088fd68",
            "name": "Tokyo",
            "type": "city"
          }
        ],   
    ]
},
{
    "_id": "6138451fb3a7d9564a0229fe"
    "title": "Event 2",
    "cohortsGroups": [
        [
          {
            "_id": "6124beef59d728c82088fd59",
            "name": "2022",
            "type": "promotion"
          }
        ]
     ]
},
{
    "_id": "6138451fb3a7d9564a0229fh"
    "title": "Event 3",
    "cohortsGroups": [
        [
          {
            "_id": "6124beef59d728c82088fd21",
            "name": "2022",
            "type": "promotion"
          },
          {
            "_id": "6124beef59d728c82088fd43",
            "name": "Amsterdam",
            "type": "city"
          }
        ]
    ]
}
 

Как вы можете видеть, поле cohortsGroups представляет собой двойной массив объектов. Я хотел бы получить эти события на основе объекта моего пользователя, который также обладает массивом (простым) cohorts

Так, например, предположим, что мой пользователь выглядит так:

 {
 "firstName": "John",
 "lastName": "Doe",
 "cohortsRef": [
   {
    "_id": "6124beef59d728c82088fd59",
    "name": "2022",
    "type": "promotion"
   },
   {
    "_id": "6124bf2159d728c82088fd60",
    "name": "Toronto",
    "type": "city"
   }
 ]
}
 

Чтобы упростить задачу, я хотел бы получить событие только в том случае, если у одного из множества cohorts входящих в него cohortsGroups есть все его когорты, представленные в объекте пользователя.

Принимая это во внимание и приведенный выше пример, я смог бы только повторить Event 1 и Event 2 . Я не могу извлечь Event 3 , потому что даже если у меня есть Когорта 2022 в моем пользователе, она сопряжена с Когортой Amsterdam , которой нет в когортах моего пользователя (eq: ни один из наборов подмножеств когорт не имеет своих значений, полностью присутствующих в когортах моего пользователя).

Я действительно надеюсь, что кто-нибудь сможет помочь мне в решении этой проблемы, до сих пор я пытался отобразить идентификаторы всех групп пользователей в массиве и запросить по $elemMatch

Events.find({ cohortsGroups: { $elemMatch: { $elemMatch: { _id: { $in: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } })

Но это решение просто извлекает каждое событие, у которого есть соответствие когорты подмассива , оно не учитывает sets , поэтому в этом случае оно также извлекало Event 3 бы — потому 2022 что присутствует — но оно сопряжено с когортой Amsterdam , которая неверна.

Дайте мне знать, если я недостаточно ясно выразился, буду признателен за любую помощь. По крайней мере, чтобы знать, выполнимо ли это как запрос монго.

Большое спасибо за чтение !

Ответ №1:

Это должно сработать:

 db.events.find({ cohortsGroups: { $elemMatch: { $not: {$elemMatch: { _id: { $nin: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } } })
 

Внешний $elemMatch , соответствует любому документу, в котором любой массив в группах когорт соответствует внутреннему условию.

Внутреннее состояние

 { $not: {$elemMatch: { _id: { $nin: [ '6124beef59d728c82088fd59', '6124bf2159d728c82088fd60' ] } } } } }
 

использует двойное отрицание с $not и $nin для поиска подмассивов, в которых нет элемента с _id , кроме тех, которые вы ищете.