Mongo sort by single enum and other field

sam*_*ura 0 mongodb

On my collection I have the fields:

{
  ...
  status: ['scheduled', 'sent', 'error']
  sendDate: Date()
}
Run Code Online (Sandbox Code Playgroud)

My objective is to show the scheduled first, and then the error and sent sorted by { sendDate: -1 }. I would do 2 queries, but I want to keep it paginated. Because of different timezones, the sendDate might end up as scheduled before other that are already sent. Like:

{
  id: 1,
  sendDate: ISODate("2019-06-11T19:28:50.617Z"),
  status: 'scheduled'
}, {
  id: 2,
  sendDate: ISODate("2019-06-12T19:28:50.617Z"),
  status: 'sent'
}, {
  id: 3,
  sendDate: ISODate("2019-06-10T19:28:50.617Z"),
  status: 'scheduled'
}, {
  id: 4,
  sendDate: ISODate("2019-06-10T19:28:50.617Z"),
  status: 'sent'
}, {
  id: 5,
  sendDate: ISODate("2019-06-11T19:28:50.617Z"),
  status: 'error'
}
Run Code Online (Sandbox Code Playgroud)

The expected sorted id's would be:

{
  id: 1,
  status: 'scheduled'
},{ 
  id: 3,
  status: 'scheduled'
},{ 
  id: 2,
  status: 'sent'
},{ 
  id: 5,
  status: 'error'
},{ 
  id: 4,
  status: 'sent'
}
Run Code Online (Sandbox Code Playgroud)

Raj*_*oel 5

您可以在运行时通过添加一个字段(优先级)并基于priority和DateTime进行排序来执行此操作;

db.collectionName.aggregate([
    {"$addFields" : {
        "priority" :  {"$cond": { if: { $eq: [ "$status", "scheduled" ] }, then: 2, else: 1 }}
        }
    },
    {"$sort" : {"priority" : -1, "sendDate" : -1}}
])
Run Code Online (Sandbox Code Playgroud)

尽管对于非常大(数百万个记录)的集合不是一个很好的解决方案。https://mongoplayground.net/p/0oEZyOyUCCH