【问题标题】:how to avoid $push-ing nulls in mongo aggregation framework如何在 mongodb 聚合框架中避免 $push 空值
【发布时间】:2017-06-30 16:24:09
【问题描述】:

$push 如果该字段不存在,则聚合空值。 我想避免这种情况。

有没有办法为 $push 运算符创建一个子表达式,这样会跳过空值而不将其推送到结果数组中?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    聚会有点晚了,但是..

    我想做同样的事情,发现我可以用这样的表达式来完成它:

      // Pushes events only if they have the value 'A'
      "events": {
        "$push": {
          "$cond": [
            {
              "$eq": [
                "$event",
                "A"
              ]
            },
            "A",
            "$noval"
          ]
        }
      }
    

    这里的想法是当你这样做时

    { "$push": "$event" } 
    

    那么它似乎只推送非空值。

    所以我编了一个不存在的列 $noval,作为我的 $cond 的错误条件返回。

    它似乎工作。我不确定它是否是非标准的,因此有一天很容易坏,但是..

    【讨论】:

    • 这可行,但它不能与索引一起使用,并且将始终使用collscan 来查看不存在的值是否存在。
    • 在我的情况下工作,谢谢。你为我节省了很多时间。
    • 谢谢$noval 为我工作:lol: 在这种情况下他们应该添加$$REMOVE
    【解决方案2】:

    如果没有示例,您的具体情况实际上并不完全清楚。 $ifNull 运算符可以用“其他”“替换”空值或缺失字段,但无法真正“跳过”。

    也就是说,您始终可以根据您的实际用例“过滤”结果。

    如果您的结果数据实际上是一个“集合”并且您的 MongoDB 版本是 2.6 或更高版本,那么您可以在 $addToSet 的帮助下使用 $setDifference 来减少保留的 null 值的数量最初:

    db.collection.aggregate([
        { "$group": {
            "_id": "$key",
            "list": { "$addToSet": "$field" }
        }},
        { "$project": {
            "list": { "$setDifference": [ "$list", [null] ] }
        }}
    ])
    

    所以只有一个null,然后$setDifference 操作将在比较中“过滤”掉它。

    在早期版本中,或者当值实际上不是“唯一”而不是“集合”时,您可以通过使用 $unwind$match 进行处理来“过滤”:

    db.collection.aggregate([
        { "$group": {
            "_id": "$key",
            "list": { "$push": "$field" }
        }},
        { "$unwind": "$list" },
        { "$match": { "list": { "$ne": null } }},
        { "$group": {
            "_id": "$_id",
            "list": { "$push": "$list" }
        }}
    ])
    

    如果您不想“破坏”最终会“空”的数组,因为它们包含“除了”null,那么您使用$ifNull 保持计数并匹配条件:

    db.collection.aggregate([
        { "$group": {
            "_id": "$key",
            "list": { "$push": "$field" },
            "count": { 
                "$sum": { 
                    "$cond": [
                        { "$eq": { "$ifNull": [ "$field", null ] }, null },
                        0,
                        1
                    ]
                }
            }
        }},
        { "$unwind": "$list" },
        { "$match": {
            "$or": [
                { "list": { "$ne": null } },
                { "count": 0 }
            ]
        }},
        { "$group": {
            "_id": "$_id",
            "list": { "$push": "$list" }
        }},
        { "$project": {
            "list": {
                "$cond": [
                    { "$eq": [ "$count", 0 ] },
                    { "$const": [] },
                    "$list"
                ]
            }
        }}
    ])
    

    使用最终的 $project 替换任何仅包含 null 值的数组,并使用空数组对象。

    【讨论】:

      猜你喜欢
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多