如何有条件地删除字段mongodb

How to remove field conditionally mongoodb

我有一个集合,其文档如下所示:

{
  _id: ObjectId('111111111122222222223333'),
  my_array: [
    {
      id: ObjectId('777777777788888888889999')
      name: 'foo'
    },
    {
      id: ObjectId('77777777778888888888555')
      name: 'foo2'
    }
    //...
  ]
  //more attributes
}

但是,有些文档有 my_array: [{}](其中一个元素是一个空数组)。

如何有条件地添加或删除投影?

我必须在查询结束时将它添加到 mongo 管道,并且我只想在它具有至少一个不是空对象的元素。如果有空对象,请将其删除。

我尝试在投影阶段使用 $cond$eq,但不支持。有什么解决这个问题的建议吗?

您不能在 query 中执行此操作,但是在聚合中,您可以将 $filter 添加到管道中,如下所示:

db.collection.aggregate([
  {
    $project: {
      my_array: {
        $filter: {
          input: "$my_array",
          as: "elem",
          cond: {
            $ne: [
              {},
              "$$elem"
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

然而,除非这是“正确”的行为,否则我建议您清理数据库,维护“正确”的结构比到处更新所有查询要简单得多。

您可以使用此更新删除这些对象:

db.collection.update({
  "myarray": {}
},
[
  {
    "$set": {
      "my_array": {
        $filter: {
          input: "$my_array",
          as: "elem",
          cond: {
            $ne: [
              {},
              "$$elem"
            ]
          }
        }
      }
    }
  },
  
],
{
  "multi": false,
  "upsert": false
})

Mongo Playground

假设您有这样的文档,其中包含 my_array 字段:

{ "my_array" : [ ] }
{ "my_array" : [ { "a" : 1 } ] }    // #(1)
{ "my_array" : null }
{ "some_fld" : "some value" }
{ "my_array" : [ {  } ] }
{ "my_array" : [ { "a" : 2 }, { "a" : 3 } ] }    // #(2)

并且,以下聚合将进行过滤,结果将包含 两个 文档 (1)(2):

db.collection.aggregate([
{
  $match: { 
      $expr: {
          $and: [ 
              { $eq: [ { $type: "$my_array" }, "array" ] },
              { $gt: [ { $size: "$my_array" }, 0 ] }, 
              { $ne: [ [{}], "$my_array" ] }
          ]
      }
  } 
}
])

这也适用于 find 方法:

db.collection.find({
    $expr: {
          $and: [ 
              { $eq: [ { $type: "$my_array" }, "array" ] },
              { $gt: [ { $size: "$my_array" }, 0 ] }, 
              { $ne: [ [{}], "$my_array" ] }
          ]
      }
})

要在文档为空时从文档中删除 my_array 字段,请尝试此聚合:

db.collection.aggregate([
{
  $addFields: { 
      my_array: {
          $cond: [
              {$and: [ 
                  { $eq: [ { $type: "$my_array" }, "array" ] },
                  { $gt: [ { $size: "$my_array" }, 0 ] }, 
                  { $ne: [ [{}], "$my_array" ] }
              ]}, 
              "$my_array", 
              "$$REMOVE"
          ]
      }
  } 
}
])

结果:

{  }
{ "my_array" : [ { "a" : 1 } ] }
{  }
{ "a" : 1 }
{  }
{ "my_array" : [ { "a" : 2 }, { "a" : 3 } ] }