Сортировать документы MongoDB по заданному c содержимому, затем по отметке времени - PullRequest
1 голос
/ 04 февраля 2020

Я использую nodejs с официальным пакетом mongodb. Я получил много документов в mongodb, содержащих поля «type» и «timestamp». Я хочу отсортировать его по приоритетам «тип» (только указав c контент), а затем «отметка времени». В качестве примера у меня есть следующие документы:

{ type: "book", timestamp: 1580825471 }
{ type: "house", timestamp: 1580825502 }
{ type: "water", timestamp: 1580825515 }
{ type: "book", timestamp: 1580825478 }
{ type: "smartphone", timestamp: 1580825522 }
{ type: "book", timestamp: 1580825424 }

Моя цель состоит в том, чтобы отсортировать таким образом по приоритету тип «книга» (а затем отсортировать его по метке времени)

{ type: "book", timestamp: 1580825478 }
{ type: "book", timestamp: 1580825471 }
{ type: "book", timestamp: 1580825424 }
{ type: "smartphone", timestamp: 1580825522 }
{ type: "water", timestamp: 1580825515 }
{ type: "house", timestamp: 1580825502 }

Я пытался использовать db.collection.aggregate со следующим значением $ sort:

$sort: {
    type: "book",
    timestamp: -1
}

Но это не сработало, поскольку значение поля $ sort может иметь значение " 1."," -1"или" {$ meta: "textScore"}".

У кого-нибудь есть идеи, как решить эту проблему?

Заранее спасибо

РЕДАКТИРОВАТЬ:

Это решение с использованием

$sort: {
  type: 1,
  timestamp: -1
}

является не решение с тех пор все типы также сортируются, чего я не хочу. Я просто хочу иметь «книгу» в качестве первого результата, а затем типы могут быть рандомизированы (но временная метка все еще сортируется). Причина этого в том, что я хочу перечислить записи истории (поэтому я использую метку времени для сортировки), но сначала я хочу показать тип «book». Даже если документ старше, чем другие документы. Так что да, для других типов ожидают «книгу», я хочу, чтобы она сортировалась по отметке времени.

Ответы [ 2 ]

3 голосов
/ 04 февраля 2020

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

Например:

db.data.aggregate([
    { $addFields : { sortPriority: { $eq: [ "$type", "book" ] } } },
    { $sort: { sortPriority: -1, timestamp: -1} }
])

Это выведет следующее:

{ "_id" : ObjectId("5e39892e0f18de54afe4d874"), "type" : "book", "timestamp" : 1580825478, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d871"), "type" : "book", "timestamp" : 1580825471, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d876"), "type" : "book", "timestamp" : 1580825424, "sortPriority" : true }
{ "_id" : ObjectId("5e39892e0f18de54afe4d875"), "type" : "smartphone", "timestamp" : 1580825522, "sortPriority" : false }
{ "_id" : ObjectId("5e39892e0f18de54afe4d873"), "type" : "water", "timestamp" : 1580825515, "sortPriority" : false }
{ "_id" : ObjectId("5e39892e0f18de54afe4d872"), "type" : "house", "timestamp" : 1580825502, "sortPriority" : false }

Если вы хотите пропустить дополнительное поле, добавьте $unset stage:

db.data.aggregate([
    { $addFields : { sortPriority: { $eq: [ "$type", "book" ] } } },
    { $sort: { sortPriority: -1, timestamp: -1} },
    { $unset: "sortPriority" }
])

Затем будет выведено:

{ "_id" : ObjectId("5e39892e0f18de54afe4d874"), "type" : "book", "timestamp" : 1580825478 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d871"), "type" : "book", "timestamp" : 1580825471 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d876"), "type" : "book", "timestamp" : 1580825424 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d875"), "type" : "smartphone", "timestamp" : 1580825522 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d873"), "type" : "water", "timestamp" : 1580825515 }
{ "_id" : ObjectId("5e39892e0f18de54afe4d872"), "type" : "house", "timestamp" : 1580825502 }
2 голосов
/ 04 февраля 2020

Вы можете создать собственный ключ сортировки:

db.col.aggregate([
   {
      $addFields: {
         sortBy: {
            $cond: {
               if: { $eq: ["$type", "book"] }, then: 0, else: 1
            }
         }
      }
   },
   { $sort: { sortBy: 1, timestamp: 1 } },
   { $unset: "sortBy" }
])

Вывод:

{ "_id" : ObjectId("5e398952227b6d209de231bb"), "type" : "book", "timestamp" : 1580825424, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b6"), "type" : "book", "timestamp" : 1580825471, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b9"), "type" : "book", "timestamp" : 1580825478, "sortPriority" : true }
{ "_id" : ObjectId("5e398952227b6d209de231b7"), "type" : "house", "timestamp" : 1580825502, "sortPriority" : false }
{ "_id" : ObjectId("5e398952227b6d209de231b8"), "type" : "water", "timestamp" : 1580825515, "sortPriority" : false }
{ "_id" : ObjectId("5e398952227b6d209de231ba"), "type" : "smartphone", "timestamp" : 1580825522, "sortPriority" : false }
...