Сортировка группы в mongo?

#mongodb

#mongodb

Вопрос:

У меня есть эта коллекция в монго :

 [
  {
    "key": "guitar",
    "name": "john"
  },
  {
    "key": "guitar",
    "name": "paul"
  },
  {
    "key": "guitar",
    "name": "george"
  },
  {
    "key": "drums",
    "name": "ringo"
  }
]
  

Я хочу сначала сгруппировать по «ключу» в порядке возрастания и отсортировать каждую группу по названию (в порядке убывания).

Я уже пробовал это :

 db.collection.aggregate([
  {
    $group: {
      _id: "$key",
      "projects": {
        "$addToSet": "$$ROOT"
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $sort: {
      "projects.key": 1,
      "projects.name": -1
    }
  },
  
])
  

Но это не сортирует name в guitar группе :

 [
  {
    "_id": "drums",
    "count": 1,
    "projects": [
      {
        "_id": ObjectId("5a934e000102030405000003"),
        "key": "drums",
        "name": "ringo"
      }
    ]
  },
  {
    "_id": "guitar",
    "count": 3,
    "projects": [
      {
        "_id": ObjectId("5a934e000102030405000000"),
        "key": "guitar",
        "name": "john" // ?????????????????????????
      },
      {
        "_id": ObjectId("5a934e000102030405000001"),
        "key": "guitar",
        "name": "paul"
      },
      {
        "_id": ObjectId("5a934e000102030405000002"),
        "key": "guitar",
        "name": "george"
      }
    ]
  }
]
  

Вопрос:

Как я могу отсортировать название элемента группы?
Живая демонстрация: https://mongoplayground.net/p/nXaN76HzLV0

Комментарии:

1. Каким тогда должен быть ожидаемый результат?

2. @KunalMukherjee барабаны, гитара …… и в гитарной группе: я ожидаю увидеть Пола, Джона, Джорджа. (имена в порядке убывания)

3. Почему сортировка по "project.key" снова, поскольку ключ должен быть одинаковым, просто сортируйте по "project.name"

4. Я хочу сначала увидеть «барабаны», а затем «гитару». вот почему я сортирую по ключу

5. В настоящее время она находится в том же порядке, который вы указали, верно

Ответ №1:

Если вы хотите использовать $addToSet , это изменит порядок значений массива, которые мы отсортировали первыми, и вы не сможете упорядочить значение массива, не размотав его (деконструировав массив), вы можете попробовать,

 db.collection.aggregate([
  {
    $group: {
      _id: "$key",
      "projects": { 
        "$addToSet": {
          name: "$name",
          key: "$key"
        } 
      },
      count: { $sum: 1 }
    }
  },
  { $unwind: "$projects" },
  { $sort: { "projects.name": -1 } },
  {
    $group: {
      _id: "$_id",
      projects: { $push: "$projects" },
      count: { $first: "$count" }
    }
  },
  { $sort: { "_id": 1 } }
])
  

Игровая площадка


Если вы используете $push вместо $addToSet , то это сработает,

 db.collection.aggregate([
  { $sort: { name: -1 } },
  {
    $group: {
      _id: "$key",
      "projects": { "$push": "$$ROOT" },
      count: { $sum: 1 }
    }
  },
  { $sort: { "_id": 1 } }
])
  

Игровая площадка


Разница между $push и $addToSet , $addToSet заменит значение, если оно уже установлено в массиве (в вашем случае $$ROOT всегда будет уникальным) и не будет поддерживать порядок документа, $push добавит все значение, даже если оно дублируется, но по порядку.

Комментарии:

1. Спасибо. что на самом деле делает unwind? из документов неясно.

2. $ unwind деконструирует массив и добавит все документы массива в root

3. $$ROOT уникален, поэтому $ addToSet ничего не заменит. Единственное отличие от $ push в этом случае заключается в том, что он изменяет порядок элементов.

4. @AlexBlex вы правы, $$ROOT всегда уникален, я исправляю это.