【问题标题】:Ignore null values when sorting by array in MongoDB在MongoDB中按数组排序时忽略空值
【发布时间】:2020-08-14 19:39:15
【问题描述】:

我有 MongoDB 集合 items 和以下文档:

{ "values" : [1, 2] }
{ "values" : [5, null] }
{ "values" : [-5, null] }

没有null 值,有没有办法通过values 属性对这个集合进行排序?我目前的查询是:

db.items.aggregate([{"$sort": {"values": 1}}])

结果如下:

{ "values" : [5, null] }
{ "values" : [-5, null] }
{ "values" : [1, 2] }

第一个值是[5, null][-5, null],因为null 是集合中的最小值。但是,我想忽略空值并仅按数字排序,所以:

{ "values" : [-5, null] }
{ "values" : [1, 2] }
{ "values" : [5, null] }

当没有数字时(两个值都是null),文档应该在结果中的最后。

【问题讨论】:

    标签: mongodb sorting


    【解决方案1】:

    你可以试试这个,

    • $addFields 使用$map 创建valuesvalues_clone,将null 替换为字符串"null",因为当我们排序时,它将排在最后
    db.collection.aggregate([
      {
        $addFields: {
          values_clone: {
            $map: {
              input: "$values",
              as: "v",
              in: {
                $cond: {
                  if: { $eq: ["$$v", null] },
                  then: "null",
                  else: "$$v"
                }
              }
            }
          }
        }
      },
    
    • $sort by values_clone 升序
      { $sort: { values_clone: 1 } },
    
    • $project 隐藏values_clone
      { $project: { values_clone: 0 } }
    ])
    

    Playground

    【讨论】:

    • 也是一个很好的解决方案(喜欢values_clone 作为标签的方法)。但是如果values 的两个元素都是[null, null],这也会丢失文档。
    • @ambianBeing,谢谢,是的,我知道这会解决这个问题,你的解决方案太好了
    【解决方案2】:

    其他选择:

    解决方案 1: 如果不需要保留数组本身中的所有 null values[] 或 null 字段。

    使用$filter 过滤掉not null 元素,(所有null 元素)数组将为空,使用$match 从文档中过滤掉它,然后在@987654333 上使用$sort @。

    db.collection.aggregate([
      {
        $project: {
          values: {
            $filter: {
              input: "$values",
              as: "d",
              cond: {
                $ne: [
                  "$$d",
                  null
                ]
              }
            }
          }
        }
      },
      {
        $match: {
          "values": {
            $ne: []
          }
        }
      },
      {
        "$sort": {
          "values": 1
        }
      }
    ]);
    

    Play Link

    解决方案 2: 不是 IMO 的好方法。但完成工作并按原样保留文档和null 值。

    首先将null 值转换为"null" 字符串,以便$sort 顺序根据字段类型起作用。使用$map"null" 字符串转换回null

    db.collection.aggregate([
      {
        $project: {
          values: {
            $map: {
              input: "$values",
              as: "d",
              in: {
                $cond: {
                  if: {
                    $eq: [
                      "$$d",
                      null
                    ]
                  },
                  then: "null",
                  else: "$$d"
                }
              }
            }
          }
        }
      },
      {
        "$sort": {
          "values": 1
        }
      },
      {
        $project: {
          values: {
            $map: {
              input: "$values",
              as: "d",
              in: {
                $cond: {
                  if: {
                    $eq: [
                      "$$d",
                      "null"
                    ]
                  },
                  then: null,
                  else: "$$d"
                }
              }
            }
          }
        }
      }
    ]);
    

    Play Link

    【讨论】:

      【解决方案3】:

      您可以使用以下阶段进行操作

      play

      db.collection.aggregate([
        {
          $unwind: "$values" //unwind them to skip null values
        },
        {
          $match: {
            "values": { //skip null values
              $ne: null
            }
          }
        },
        {
          "$sort": { //sorting pipeline
            "values": 1
          }
        },
        {
          $group: { //regrouping them
            "_id": "$_id",
            "values": {
              $push: "$values"
            }
          }
        }
      ])
      

      如果您想忽略整个数组,即使一个值为空,您可以跳过unwindgroup 阶段。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-31
        • 2016-10-20
        • 1970-01-01
        • 2011-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多