MongoDB: получить самые последние объекты из встроенных массивов и добавить родительское поле - PullRequest
0 голосов
/ 07 января 2020

У меня есть множество компаний, где у каждой компании есть множество объектов подписки. Объект подписки имеет массив элементов и дату, когда эти элементы были добавлены. Я хочу получить только последний добавленный объект подписки от каждой компании. Мне также нужно иметь возможность определить, откуда появился каждый объект подписки, поэтому мне нужно как-то добавить название компании. Извините за запутанную семантику!

Массив компаний:

[
  {
    "_id": "company1",
    "name": "Company 1",
    "subscriptions": [
      {
        "items": [
          {
            "_id": "5e13b0207b05e37f12f05beb",
            "data": 40,
            "price": 39
          },
          {
            "_id": "5e13b0207b05e37f12f05bea",
            "data": 100,
            "price": 59
          }
        ],
        "_id": "5e13b0207b05e37f12f05be9",
        "date_added": "2019-12-24T22:09:36.442Z"
      }
    ]
  },
  { "_id": "company2", "name": "Company 2", "subscriptions": [] },
  {
    "_id": "company3",
    "name": "Company 3",
    "subscriptions": [
      {
        "items": [
          {
            "_id": "5e13a47d7c370667c7e67d7a",
            "data": 40,
            "price": 69
          },
          {
            "_id": "5e13a47d7c370667c7e67d79",
            "data": 20,
            "price": 39
          }
        ],
        "_id": "5e13a47d7c370667c7e67d78",
        "date_added": "2019-12-24T21:19:57.804Z"
      },
      {
        "items": [
          {
            "_id": "5e13a4f87c370667c7e67d7d",
            "data": 35,
            "price": 39
          },
          {
            "_id": "5e13a4f87c370667c7e67d7c",
            "data": 60,
            "price": 59
          }
        ],
        "_id": "5e13a4f87c370667c7e67d7b",
        "date_added": "2020-01-04T21:22:00.832Z"
      }
    ]
  }
]

Желаемый выход:

[
  {
    "name": "Company 1",
    "items": [
      {
        "_id": "5e13b0207b05e37f12f05beb",
        "data": 40,
        "price": 39
      },
      {
        "_id": "5e13b0207b05e37f12f05bea",
        "data": 100,
        "price": 59
      }
    ],
    "_id": "5e13b0207b05e37f12f05be9",
    "date_added": "2019-12-24T22:09:36.442Z"
  },
  {
    "name": "Company 3",
    "items": [
      {
        "_id": "5e13a4f87c370667c7e67d7d",
        "data": 35,
        "price": 39
      },
      {
        "_id": "5e13a4f87c370667c7e67d7c",
        "data": 60,
        "price": 59
      }
    ],
    "_id": "5e13a4f87c370667c7e67d7b",
    "date_added": "2020-01-04T21:22:00.832Z"
  }
]

Что я пытаюсь:

await Companies.aggregate([
  { $unwind: '$subscriptions' },
  { $sort: { 'subscriptions.date_added': -1 } },
  { $group: { _id: '$_id' } }
])

Вывод:

[{"_id":"company1"},{"_id":"company3"}]

Мне кажется, я отфильтровал правильные объекты (самые последние), но я получаю только _id элемента root, а не вложенные объекты подписки. Эти идентификаторы могут использоваться для идентификации подписок, но мне также нужны фактические элементы подписки.

Ответы [ 2 ]

1 голос
/ 07 января 2020

В вашем решении вам нужно накапливать подписки с оператором $first и с $project вы можете получить желаемый результат.

db.companies.aggregate([
  {
    $unwind: "$subscriptions"
  },
  {
    $sort: {
      "subscriptions.date_added": -1
    }
  },
  {
    $group: {
      _id: "$_id",
      name: {
        $first: "$name"
      },
      subscriptions: {
        $first: "$subscriptions"
      }
    }
  },
  {
    $project: {
      _id: "$subscriptions._id",
      name: "$name",
      date_added: "$subscriptions.date_added",
      items: "$subscriptions.items"
    }
  }
])

MongoPlayground

1 голос
/ 07 января 2020

Поскольку все, что вам нужно, это последний объект подписки, если это означает, что это последний объект, помещаемый в массив subscriptions, попробуйте следующее:

Companies.aggregate([{$match : {$and :[{subscriptions: {$exists: true}}, {subscriptions: {$ne: []}}]}},
{$addFields :{subscriptions: {$arrayElemAt : ['$subscriptions',-1]} }}, {$project :{_id:0,subscriptions:1, name:1 }}])

Данные сбора:

/* 1 */
{
    "_id" : "company1",
    "name" : "Company 1",
    "subscriptions" : [ 
        {
            "items" : [ 
                {
                    "_id" : "5e13b0207b05e37f12f05beb",
                    "data" : 40.0,
                    "price" : 39.0
                }, 
                {
                    "_id" : "5e13b0207b05e37f12f05bea",
                    "data" : 100.0,
                    "price" : 59.0
                }
            ],
            "_id" : "5e13b0207b05e37f12f05be9",
            "date_added" : "2019-12-24T22:09:36.442Z"
        }
    ]
}

/* 2 */
{
    "_id" : "company2",
    "name" : "Company 2",
    "subscriptions" : []
}

/* 3 */
{
    "_id" : "company3",
    "name" : "Company 3",
    "subscriptions" : [ 
        {
            "items" : [ 
                {
                    "_id" : "5e13a47d7c370667c7e67d7a",
                    "data" : 40.0,
                    "price" : 69.0
                }, 
                {
                    "_id" : "5e13a47d7c370667c7e67d79",
                    "data" : 20.0,
                    "price" : 39.0
                }
            ],
            "_id" : "5e13a47d7c370667c7e67d78",
            "date_added" : "2019-12-24T21:19:57.804Z"
        }, 
        {
            "items" : [ 
                {
                    "_id" : "5e13a4f87c370667c7e67d7d",
                    "data" : 35.0,
                    "price" : 39.0
                }, 
                {
                    "_id" : "5e13a4f87c370667c7e67d7c",
                    "data" : 60.0,
                    "price" : 59.0
                }
            ],
            "_id" : "5e13a4f87c370667c7e67d7b",
            "date_added" : "2020-01-04T21:22:00.832Z"
        }
    ]
}

Результат:

/* 1 */
{
    "name" : "Company 1",
    "subscriptions" : {
        "items" : [ 
            {
                "_id" : "5e13b0207b05e37f12f05beb",
                "data" : 40.0,
                "price" : 39.0
            }, 
            {
                "_id" : "5e13b0207b05e37f12f05bea",
                "data" : 100.0,
                "price" : 59.0
            }
        ],
        "_id" : "5e13b0207b05e37f12f05be9",
        "date_added" : "2019-12-24T22:09:36.442Z"
    }
}

/* 2 */
{
    "name" : "Company 3",
    "subscriptions" : {
        "items" : [ 
            {
                "_id" : "5e13a4f87c370667c7e67d7d",
                "data" : 35.0,
                "price" : 39.0
            }, 
            {
                "_id" : "5e13a4f87c370667c7e67d7c",
                "data" : 60.0,
                "price" : 59.0
            }
        ],
        "_id" : "5e13a4f87c370667c7e67d7b",
        "date_added" : "2020-01-04T21:22:00.832Z"
    }
}
...