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

时间:2017-07-09 20:58:26

标签: mongodb mongodb-query

我有一些关于具有 SetApplicationFavicon(id,basepath,icon) { $("#"+id).attr("href", basepath+"/"+icon); } 属性的实体的文档集合,可以是status1。每个文档都包含大量数据并占用空间。 我希望摆脱0等于status的文档中的大部分数据。

所以,我希望集合中的每个文档看起来都像

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
}

但是大约有40个属性是一个巨大的列表,而且我还不确定所有对象是否遵循相同的模式。

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

1 个答案:

答案 0 :(得分:1)

这里最好的做法是将所有可能的属性扔到$unset并让它完成它的工作。你不能"通配符"这样的论点所以如果没有写入另一个集合,确实没有更好的方法。

如果您不想全部输入或甚至全部知道它们,那么只需执行一个过程即可收集"收集"所有其他顶级房产。

您可以使用.mapReduce()

执行此操作
var fields = db.getCollection('docs').mapReduce(
  function() {
    Object.keys(this)
      .filter(k => k !== '_id' && k  !== 'myCode')
      .forEach( k => emit(k,1) )
  },
  function() {},
  {
    "out": { "inline": 1 }   
  }
).results.map( o => o._id )
 .reduce((acc,curr) => Object.assign(acc,{ [curr]: "" }),{})

为您提供一个包含完整字段列表的对象,以便提供给$unset

{
    "a" : "",
    "and" : "",
    "lot" : "",
    "more" : "",
    "name" : "",
    "properties" : "",
    "status" : ""
}

这取自整个集合中所有可能的顶级字段。

您可以使用.aggregate()在MongoDB 3.4中使用$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]: "" }),{});

无论您以何种方式获取姓名列表,只需将其发送至$unset

即可
db.getCollection('docs').update(
  { "statusCode": 0 },
  { "$unset": fields },
  { "multi": true }
)

底部就是$unset并不关心文档中是否存在属性,而只是将它们移除到存在的位置。

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

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