MongoDB sort documents by array elements

后端 未结 1 541
既然无缘
既然无缘 2020-12-01 09:27

I have document structure like :

{
    map: \'A\',
    points: [
        {
            type: \'type1\',
            d         


        
相关标签:
1条回答
  • 2020-12-01 09:56

    You cannot do that with arrays, and the main problem here is because you want the "sort" to happen on the matched element. If you want to sort results like this then you need to use .aggregate() instead. Either as:

    For modern MongoDB versions:

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

    For MongoDB 2.6 to 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 } },
    ]);
    

    Or less efficiently in versions prior to 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 } }         
    ])
    

    That's the only way to match the correct elements and have them considered in a "sort" operation. The default cursor sort will just otherwise consider the values for the field in the array elements that do not match your selected "type" instead.

    0 讨论(0)
提交回复
热议问题