2015-03-05 12 views
6

io abbiamo la struttura del documento come:documenti MongoDB sort by elementi dell'array

{ 
    map: 'A', 
    points: [ 
     { 
      type: 'type1', 
      distanceToSpawn: 110 
     }, 
     { 
      type: 'type4', 
      distanceToSpawn: 40 
     }, 
     { 
      type: 'type6', 
      distanceToSpawn: 30 
     } 
    ] 
}, 
{ 
    map: 'B', 
    points: [ 
     { 
      type: 'type1', 
      distanceToSpawn: 100 
     }, 
     { 
      type: 'type2', 
      distanceToSpawn: 60 
     }, 
     { 
      type: 'type3', 
      distanceToSpawn: 25 
     } 
    ] 
}, 
{ 
    map: 'C', 
    points: [ 
     { 
      type: 'type2', 
      distanceToSpawn: 90 
     }, 
     { 
      type: 'type3', 
      distanceToSpawn: 1 
     }, 
     { 
      type: 'type6', 
      distanceToSpawn: 76 
     } 
    ] 
} 

voglio ottenere tutte le mappe che hanno tipo punto type1 ordinato dal distanceToSpawn in ordine crescente.

Risultato atteso:

{ 
    map: 'B', 
    points: [ 
     { 
      type: 'type1', 
      distanceToSpawn: 100 
     } 
    ] 
}, 
{ 
    map: 'A', 
    points: [ 
     { 
      type: 'type1', 
      distanceToSpawn: 110 
     } 
    ] 
} 

ho provato qualcosa di simile:

db.maps.find({'points.type': {$eq : 'type1'}}, {map: 1, 'points.$':1}).sort({'points.distanceToSpawn': 1}).limit(10) 

Ma questa cosa non l'ordinamento mappe per ordine crescente.

Grazie.

risposta

7

Non è possibile farlo con gli array, e il problema principale qui è perché si desidera che "l'ordinamento" si verifichi sull'elemento corrispondente. Se vuoi ordinare risultati come questo, allora devi usare .aggregate(). Sia come:

Per le versioni MongoDB moderne:

db.maps.aggregate([ 
    { "$match": { "points.type": "type1" }}, 
    { "$addFields": { 
     "order": { 
      "$filter": { 
       "input": "$points", 
       "as": "p", 
       "cond": { "$eq": [ "$$p.type", "type1" ] } 
      } 
     } 
    }}, 
    { "$sort": { "order": 1 } } 
]) 

Per MongoDB 2.6 a 3,0

db.maps.aggregate([ 
    { "$match": { "points.type": "type1" }}, 
    { "$project": { 
     "points": { 
      "$setDifference": ] 
       { "$map": { 
        "input": "$points", 
        "as": "p", 
        "in": { "$cond": [ 
         { "$eq": [ "$$p.type", "$type1" ] }, 
         "$$p", 
         false 
        ]} 
       }}, 
       [false] 
      ] 
     } 
    }}, 
    { "$sort": { "points.distanceToSpawn": 1 } } 
]) 

o meno efficiente nelle versioni precedenti alla MongoDB 2.6:

db.maps.aggregate([ 
    { "$match": { "points.type": "type1" }}, 
    { "$unwind": "$points" }, 
    { "$match": { "points.type": "type1" }}, 
    { "$group": { 
     "_id": "$id", 
     "points": { "$push": "$points" } 
    }}, 
    { "$sort": { "points.ditanceToSpawn": 1 } }   
]) 

Questo è il unico modo per abbinare gli elementi corretti e tenerli in considerazione in un'operazione di "ordinamento". L'ordinamento del cursore predefinito considererà solo i valori per il campo negli elementi dell'array che non corrispondono al "tipo" selezionato.

Problemi correlati