MongoDB 按数组元素对文档进行排序 [英] MongoDB sort documents by array elements

查看:24
本文介绍了MongoDB 按数组元素对文档进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的文档结构如下:

{
    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
        }
    ]
}

我想获取所有点类型为 type1 的地图,按 distanceToSpawn 升序排序.

I want to get all maps having point type type1 sorted by the distanceToSpawn in ascending order.

预期结果:

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

我试过类似的东西:

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

但这东西不是按升序排列地图的.

But this thing not sorting maps by ascending order.

谢谢.

推荐答案

你不能用数组做到这一点,这里的主要问题是你希望排序"发生在匹配的元素上.如果你想像这样对结果进行排序,那么你需要使用 .aggregate() 代替.要么是:

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:

对于现代 MongoDB 版本:

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 } }
])

对于 MongoDB 2.6 到 3.0

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 } },
]);

在 MongoDB 2.6 之前的版本中效率更低:

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.

这篇关于MongoDB 按数组元素对文档进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆