MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB trier les documents par éléments de tableau

Vous ne pouvez pas faire cela avec des tableaux, et le principal problème ici est que vous voulez que le "tri" se produise sur l'élément correspondant. Si vous voulez trier les résultats comme celui-ci, vous devez utiliser .aggregate() Au lieu. Soit en tant que :

Pour les versions modernes de MongoDB :

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

Pour MongoDB 2.6 à 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 } },
]);

Ou moins efficacement dans les versions antérieures à 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 } }         
])

C'est le seul moyen de faire correspondre les éléments corrects et de les prendre en compte dans une opération de "tri". Sinon, le tri par défaut du curseur prendra simplement en compte les valeurs du champ dans les éléments du tableau qui ne correspondent pas à votre "type" sélectionné à la place.