从MongoDB查询结果中省略空字段

4
有没有一种方法可以从MongoDB查询结果的文档(find或aggregate)中省略空字段(例如空字符串或空数组)。

数据库中的文档:

{
    "_id" : ObjectId("5dc3fcb388c1c7c5620ed496"),
    "name": "Bill",
    "emptyString" : "",
    "emptyArray" : []
}

输出:

{
    "_id" : ObjectId("5dc3fcb388c1c7c5620ed496"),
    "name": "Bill"
}

关于 Elasticsearch 的类似问题:如何从 Elasticsearch 结果中省略 null 字段

3个回答

6
请使用聚合函数。如果要删除键,则可以使用 $cond 并在 $project 中使用它。
db.Speed.aggregate( [
   {
      $project: {
         name: 1,
         "_id": 1,
         "emptyString": {
            $cond: {
               if: { $eq: [ "", "$emptyString" ] },
               then: "$$REMOVE",
               else: "$emptyString"
            }
         },
         "emptyArray": {
            $cond: {
               if: { $eq: [ [], "$emptyArray" ] },
               then: "$$REMOVE",
               else: "$emptyArray"
            }
         }
      }
   }
] )

这提供了一些见解。谢谢!是否可以一次为所有字段完成,而不必为每个字段编写冗余代码? - Sagar Gupta
谢谢这个。这对我很有帮助。 - keshav.bahadoor

0

我认为从输出中删除所有空字符串和空数组字段的最简单方法是添加以下聚合阶段。 (是的,“简单”是相对的,当您必须创建这些逻辑层次来完成如此琐碎的任务时...)

$replaceRoot: {
  newRoot: {
    $arrayToObject: {
      $filter: {
        input: {
          $objectToArray: '$$ROOT'
        },
        as: 'item',
        cond: {
          $and: [
            { $ne: [ '$$item.v', [] ] },
            { $ne: [ '$$item.v', '' ] }
          ]
        }
      }
    }
  }
}

只需修改条件子句以过滤掉其他类型的字段(例如null)。

顺便说一下:我还没有测试过它的性能,但至少它是通用的并且有点可读。

编辑:重要! $replaceRoot 阶段会阻止 MongoDB 优化管道,因此如果您在运行 .find() 的视图中使用它,它将在视图的管道末尾附加一个 $match 阶段,而不是在管道开头添加索引搜索。这将对性能产生重大影响。您可以安全地在自定义管道中使用它,只要在其之前有 $match 阶段即可。(至少根据我的有限 MongoDB 知识)。如果有人知道如何在查询时将 $match 阶段预置到视图中,请留言 :-)


0

一种实现方法是使用cursor.map(),该方法可用于find()aggregation([])

其思路是先列出文档中存在或可能存在的字段列表,然后使用delete运算符过滤掉返回文档中的空字符串或空数组字段(两者都具有length属性)。

Mongo Shell:

var fieldsList = ["name", "emptyString", "emptyArray"];

db.collection.find().map(function(d) {
  fieldsList.forEach(function(k) {
    if (
      k in d &&
      (Array.isArray(d[k]) ||
        (typeof d[k] === "string" || d[k] instanceof String)) &&
      d[k].length === 0
    ) {
      delete d[k];
    }
  });
  return d;
});

测试文档:

{
  "_id" : ObjectId("5dc426d1f667120607ac5006"),
  "name" : "Bill",
  "emptyString" : "",
  "emptyArray" : [ ]
}
{
  "_id" : ObjectId("5dc426d1f667120607ac5007"),
  "name" : "Foo",
  "emptyString" : "foo",
  "emptyArray" : [ ]
}
{
  "_id" : ObjectId("5dc426d1f667120607ac5008"),
  "name" : "Bar",
  "emptyString" : "",
  "emptyArray" : [
          "foo",
          "bar"
  ]
}
{
  "_id" : ObjectId("5dc426d1f667120607ac5009"),
  "name" : "May",
  "emptyString" : "foobar",
  "emptyArray" : [
          "foo",
          "bar"
  ]
}

输出

[
        {
                "_id" : ObjectId("5dc426d1f667120607ac5006"),
                "name" : "Bill"
        },
        {
                "_id" : ObjectId("5dc426d1f667120607ac5007"),
                "name" : "Foo",
                "emptyString" : "foo"
        },
        {
                "_id" : ObjectId("5dc426d1f667120607ac5008"),
                "name" : "Bar",
                "emptyArray" : [
                        "foo",
                        "bar"
                ]
        },
        {
                "_id" : ObjectId("5dc426d1f667120607ac5009"),
                "name" : "May",
                "emptyString" : "foobar",
                "emptyArray" : [
                        "foo",
                        "bar"
                ]
        }
]

注意:如果文档中字段的数量非常大,这可能不是最优解决方案,因为将会与文档中的所有字段进行比较。您可能需要将fieldsList分块,使用怀疑为空数组或字符串的属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接