Проецирование значений массива в документе монго на основе полей, отличных от массива

Данные в моей базе следующие:

/* 1 */
{
      "name": "Severus",
      "u_name": "severussnape",
      "info": [
        {
          "value": "Severus",
          "source": "1",
          "infotag": "name"
        },
        {
          "value": "severussnape",
          "source": "2",
          "infotag": "name"
        }
      ]
}

/* 2 */
{
      "name": "Harry",
      "u_name": null,
      "info": [
        {
        "value": "Harry",
          "source": "1",
          "infotag": "name"
        }
      ]
}

Я хотел бы проецировать данные так, чтобы поле name и массив info в результате изменялись в зависимости от того, является ли поле u_name нулевым. Ожидаемый результат выглядит так:

/* 1 */
{
      "name": "severussnape",
      "info": [
        {
          "value": "severussnape",
          "source": "2",
          "infotag": "name"
        }
      ]
}

/* 2 */
{
      "name": "Harry",      
      "info": [
        {
          "value": "Harry",
          "source": "1",
          "infotag": "name"
        }
      ]
}

Мне удалось правильно спроецировать поле имени, используя проекцию:

db.database.aggregate([{
    $project:{
        "name":{$cond:[{$eq:["$u_name",null]},"$name","$u_name"]}
    }
}])

Но я не смог понять, как удалить элемент массива из info со значением «Северус» в первом документе в зависимости от u_name. Это возможно?

Вы можете получить желаемые результаты с помощью $unwind, но я до сих пор не понимаю, как именно вы хотите удалить поддокумент с именем «Северус».

Jitendra 13.03.2019 07:30

@Jitendra, извините, я не ясно выразился. Элемент массива с именем «Северус» (или из источника 1, если быть шире) необходимо удалить, если поле u_name не равно нулю.

sudhanva 13.03.2019 07:35
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
2
36
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете попробовать что-то вроде ниже:

db.database.aggregate([
    {
        $project:{
            "name":{ $cond: { if: { $eq:["$u_name",null] }, then: "$name", else: "$u_name" } },
        }
    },
])

Это эквивалентно запросу, который я предоставил в своем вопросе, если я не ошибаюсь.

sudhanva 13.03.2019 09:26

Это полезно?

если любое условие нужно. Вы можете соответствовать этому.

db.getCollection('TestQueries').aggregate([
{$unwind:{
 path:"$info",
 preserveNullAndEmptyArrays:true
}},
{$project:{
  name:"$info.value",
  info:1
}}
])
Ответ принят как подходящий

Вы должны попробовать этот совокупный запрос, это решит вашу проблему.

db.database.aggregate([
    {
        $project:{
            'name': {
                '$ifNull': ['$u_name', '$name']
            },
            'info': '$info'
        }
    },
    {
        $project: {
            'name': '$name',
            'info': {
                '$filter': {
                    'input': '$info',
                    'as': 'info',
                    'cond': {
                        '$eq':['$$info.value', '$name']
                    }
                }
            }
        }
    }
])

Другие вопросы по теме