Il problema di base con ciò che stai chiedendo qui si riduce al fatto che i dati in questione si trovano all'interno di un "array", e quindi ci sono alcune ipotesi di base fatte da MongoDB su come questo viene gestito.
Se hai applicato un ordinamento in "ordine decrescente", MongoDB eseguirà esattamente ciò che chiedi e ordinerà i documenti in base al valore "più grande" del campo specificato all'interno dell'array:
.sort({ "revisions.created": -1 ))
Ma se invece ordini in ordine "crescente", ovviamente è vero il contrario e viene considerato il valore "più piccolo".
.sort({ "revisions.created": 1 })
Quindi l'unico modo per farlo significa calcolare quale è la data massima dai dati nell'array e quindi ordinare in base a quel risultato. Ciò significa sostanzialmente applicare .aggregate()
, che per meteor è un'operazione lato server, essendo purtroppo qualcosa del genere:
Collection.aggregate([
{ "$unwind": "$revisions" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"revisions": { "$push": "$revisions" },
"number": { "$first": "$number" }
"maxDate": { "$max": "$revisions.created" }
}},
{ "$sort": { "maxDate": 1 }
])
O al massimo con MongoDB 3.2, dove $max
può essere applicato direttamente a un'espressione di matrice:
Collection.aggregate([
{ "$project": {
"name": 1,
"revisions": 1,
"number": 1,
"maxDate": {
"$max": {
"$map": {
"input": "$revisions",
"as": "el",
"in": "$$el.created"
}
}
}
}},
{ "$sort": { "maxDate": 1 } }
])
Ma in realtà entrambi non sono il massimo, anche se l'approccio MongoDB 3.2 ha un sovraccarico molto inferiore rispetto a quello disponibile per le versioni precedenti, non è comunque così buono come puoi ottenere in termini di prestazioni a causa della necessità di passare attraverso i dati e lavorare il valore su cui eseguire l'ordinamento.
Quindi per il meglio prestazioni, mantieni "sempre" i dati di cui avrai bisogno "fuori" dall'array. Per questo c'è il $max
operatore "aggiorna", che sostituirà un valore all'interno del documento solo "se" il valore fornito è "maggiore di" il valore esistente già presente. cioè:
Collection.update(
{ "_id": "qTF8kEphNoB3eTNRA" },
{
"$push": {
"revisions": { "created": new Date("2016-02-01") }
},
"$max": { "maxDate": new Date("2016-02-01") }
}
)
Ciò significa che il valore che desideri sarà "sempre" già presente all'interno del documento con il valore atteso, quindi è solo ora una semplice questione di ordinamento su quel campo:
.sort({ "maxDate": 1 })
Quindi, per i miei soldi, esaminerei i dati esistenti con uno dei .aggregate()
istruzioni disponibili e utilizzare tali risultati per aggiornare ogni documento in modo che contenga un campo "maxDate". Quindi cambia la codifica di tutte le aggiunte e le revisioni dei dati dell'array per applicare quel $max
"aggiorna" ad ogni modifica.
Avere un campo solido piuttosto che un calcolo ha sempre molto più senso se lo usi abbastanza spesso. E la manutenzione è abbastanza semplice.
In ogni caso, considerando la data di esempio applicata sopra, che è "inferiore" alle altre date massime presenti mi ritornerei in tutte le forme:
{
"_id" : "5xF9iDTj3reLDKNHh",
"name" : "Lorem ipsum",
"revisions" : [
{
"number" : 0,
"comment" : "Dolor sit amet",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 1,
"maxDate" : ISODate("2016-02-11T01:22:45.588Z")
}
{
"_id" : "qTF8kEphNoB3eTNRA",
"name" : "Consecitur quinam",
"revisions" : [
{
"comment" : "Hoste ad poderiquem",
"number" : 1,
"created" : ISODate("2016-02-11T23:25:46.033Z")
},
{
"number" : 0,
"comment" : "Fagor questibilus",
"created" : ISODate("2016-02-11T01:22:45.588Z")
},
{
"created" : ISODate("2016-02-01T00:00:00Z")
}
],
"number" : 2,
"maxDate" : ISODate("2016-02-11T23:25:46.033Z")
}
Che posiziona correttamente il primo documento all'inizio dell'ordinamento tenendo conto del "maxDate".