Элемент массива проекта mongoDB после фильтра - PullRequest
0 голосов
/ 29 мая 2020

У меня есть следующая (упрощенная) агрегация:

Model.aggregate([
    {
      $lookup: {
        from: 'orders',
        localField: '_id',
        foreignField: 'customer',
        as: 'orders',
      },
    },
    {
      $project: {
        openOrders: {
          $filter: {
            input: '$orders',
            as: 'order',
            cond: { $eq: ['$$order.status', 'open'] },
          },
        },
      },
    },        
  ])

, которая возвращает следующее:

{
  _id: ...,
  openOrders: [
    [Object], [Object]
  ],
}

Эти [Object] - это просто возвращенные объекты, сохраняемые в базу данных со всеми их полями.

Я не нахожу способа проецировать / отфильтровывать поля этих объектов и вместо этого возвращаю только их _id:

{
  _id: ...,
  openOrders: [
    _id: ...,
    _id: ....
  ],
}

EDIT : Я бы предпочел следующий ожидаемый результат:

{
  _id: ...,
  openOrders: [
    { _id: ... },
    { _id: ... }
  ],
}

Я безуспешно пытался добавить новый этап $project в различные точки агрегации. Кто-нибудь может мне помочь?

Ответы [ 2 ]

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

Поскольку вам нужен массив из _id, как этот

openOrders: [ _id: ..., _id: .... ]

, но не массив из _id в объектах:

openOrders: [ {_id: ...}, {_id: ....} ]

Вам необходимо используйте $ reduce вместо $filter:

Попробуйте запрос ниже:

 db.collection.aggregate([
    {
      $project: {
        openOrders: {
          $reduce: {
            input: "$orders", // Same like `$filter` use reduce to iterate on array
            initialValue: [], // consider an initial value
            in: { // If condition is met, push value to array else return holding array as is.
              $cond: [ { $eq: [ "$$this.status", "open" ] },
                { $concatArrays: [ "$$value", [ "$$this._id" ] ] },
                "$$value"
              ]
            }
          }
        }
      }
    }
  ])

Тест: mongoplayground

Примечание: В javaScript - если вы печатаете JSON с объектами, вам нужно напечатать его с JSON.stringify(yourJSON) - что делает его строка, чтобы вы не видели [Object], [Object] в консоли, а видели бы реальные объекты.

Обновление:

Если вам нужен массив объектов с * Поле 1035 * просто добавьте еще один этап $project в конце, но я настоятельно рекомендую использовать $reduce и получить массив для вашего сценария:

{ $project: { "openOrders._id": 1 } } // which would just extract `_id` fields in each objects

Тест: игровая площадка

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

Вы должны добавить стадию $project, как показано ниже:

{
  $project: {
    openOrders: 'openOrders._id'
  }
}

Это даст следующий результат:

{
  _id: ...,
  openOrders: [
    _id1,
    _id2,
    ...
  ],
}

вместо

{
  _id: ...,
  openOrders: [
    _id: ...,
    _id: ....
  ],
}

Я предлагаю этот тип запроса, потому что, если вы действительно видите openOrders, это просто массив _id s, поэтому добавление только одного поля _id внутри массива не имеет смысла.

If вы по-прежнему хотите, чтобы вывод был похож на массив объектов, тогда вы можете использовать следующее:

{
  $project: {
    'openOrders._id': 1
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...