MongoDB 按数组元素对文档进行排序

标签 mongodb sorting mongodb-query aggregation-framework

我的文档结构如下:

{
    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 的 map ,按 distanceToSpawn 升序排序。

预期结果:

{
    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)

但这东西不是按升序排列 map 的。

谢谢。

最佳答案

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

对于现代 MongoDB 版本:

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

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 之前的版本中效率更低:

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

这是匹配正确元素并在“排序”操作中考虑它们的唯一方法。默认的光标排序只会考虑数组元素中与您选择的“类型”不匹配的字段值。

关于MongoDB 按数组元素对文档进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28889240/

相关文章:

java - 如何将 JSON 对象转换为 DBObject?

MongoDB 从文档中提取子数组

MongoDB $text 运算符匹配文档,其中搜索字符串是子字符串

java - 将文档插入 MongoDB 中的另一个文档

php认证/数据库代码风格

c# - 更新多级嵌入式mongo数组

java - 如何在不使用 Collections.sort() 的情况下按值对 LinkedHashMap 进行排序?

C# Winforms - 未绑定(bind) DataGridView 的辅助排序

ruby - 根据字符串的最后一个单词对数组进行排序

node.js - 当前端取消请求时,如何让 Express.js 中止 MongoDB 请求?