如何在mongodb中取消设置除一个或两个之外的所有文档属性?

如何在mongodb中取消设置除一个或两个之外的所有文档属性?,mongodb,mongodb-query,Mongodb,Mongodb Query,我有一个关于实体的文档集合,这些实体具有状态属性,可以是1或0。每个文档都包含大量数据并占用空间。 我想删除状态为statusequal0的文档上的大部分数据 因此,我希望集合中的每个文档 { _id: 234, myCode: 101, name: "sfsdf", status: 0, and: 23243423.1, a: "dsf", lot: 3234, more: "efsfs", properties: "sdfsd"

我有一个关于实体的文档集合,这些实体具有
状态
属性,可以是
1
0
。每个文档都包含大量数据并占用空间。 我想删除状态为
status
equal
0
的文档上的大部分数据

因此,我希望集合中的每个文档

{
   _id: 234,
   myCode: 101,
   name: "sfsdf",
   status: 0,    
   and: 23243423.1,
   a: "dsf",
   lot: 3234,
   more: "efsfs",
   properties: "sdfsd"
}
…要小得多

{
    _id: 234,
    mycode: 101,
    status: 0
}
所以,基本上我能做到

db.getCollection('docs').update(
    {'statusCode': 0},
    { 
        $unset: { 
           and: "", 
           a: "", 
           lot: "", 
           more: "", 
           properties: "" 
       } 
    }, 
    {multi:true}
)
但是有大约40个属性,这将是一个巨大的列表,而且我不确定所有的对象都遵循相同的模式


有没有办法取消设置除两个属性之外的所有属性?

这里最好的做法是将所有可能的属性都抛出,让它完成它的工作。您不能“通配符”这样的参数,因此没有更好的方法不写入另一个集合

如果您不想将它们全部输入,甚至不想知道它们的全部,那么只需执行一个过程来“收集”所有其他顶级属性

例如,您可以使用
.mapReduce()

为您提供一个包含完整字段列表的对象,以作为:

这是从整个集合中所有可能的顶级字段中获取的

您可以使用MongoDB 3.4中的
.aggregate()
使用
$objectToArray
执行相同的操作:

var fields = db.getCollection('docs').aggregate([
  { "$project": {
    "fields": {
      "$filter": {
        "input": { "$objectToArray": "$$ROOT" },
        "as": "d",
        "cond": {
          "$and": [
            { "$ne": [ "$$d.k", "_id" ] },
            { "$ne": [ "$$d.k", "myCode" ] }          
          ]
        }
      }
    }  
  }},
  { "$unwind": "$fields" },
  { "$group": {
    "_id": "$fields.k"  
  }}
]).map( o => o._id )
  .reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{});
无论您以何种方式获得姓名列表,只需将其发送至:

类似于Bottom的是,它不关心这些属性是否存在于文档中,只会在它们存在的地方删除它们


另一种情况是,如果符合您的需要,只需将所有内容写入新的集合。这是作为聚合管道阶段的简单使用:

db.getCollection('docs').aggregate([
  { "$match": { "statusCode": 0 } },
  { "$project": { "myCode": 1  } },
  { "$out": "newdocs" }
])

您应该只覆盖而不是取消设置。类似于
db.getCollection('docs').update({'statusCode':0},{{u id:234,mycode:101,status:0})
并使用批量写入。我想到了这一点,但有两个缺陷:1。覆盖不适用于
multi
参数。2.我需要保留可能不同的
mycode
s,我不知道如何使用此方法保存它们。抱歉,我仍在更新我的评论。再次检查。是的,但是如何保持各种
mycode
s未被触动?
var fields = db.getCollection('docs').aggregate([
  { "$project": {
    "fields": {
      "$filter": {
        "input": { "$objectToArray": "$$ROOT" },
        "as": "d",
        "cond": {
          "$and": [
            { "$ne": [ "$$d.k", "_id" ] },
            { "$ne": [ "$$d.k", "myCode" ] }          
          ]
        }
      }
    }  
  }},
  { "$unwind": "$fields" },
  { "$group": {
    "_id": "$fields.k"  
  }}
]).map( o => o._id )
  .reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{});
db.getCollection('docs').update(
  { "statusCode": 0 },
  { "$unset": fields },
  { "multi": true }
)
db.getCollection('docs').aggregate([
  { "$match": { "statusCode": 0 } },
  { "$project": { "myCode": 1  } },
  { "$out": "newdocs" }
])