我有一些关于具有 SetApplicationFavicon(id,basepath,icon)
{
$("#"+id).attr("href", basepath+"/"+icon);
}
属性的实体的文档集合,可以是status
或1
。每个文档都包含大量数据并占用空间。
我希望摆脱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个属性是一个巨大的列表,而且我还不确定所有对象是否遵循相同的模式。
有没有办法取消除两个属性之外的所有属性?
答案 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" }
])