我有一些如下所示的数据:
{
"name" : "someValue",
"date" : "someValue",
"age" : "someValue",
"price" : "someValue",
"sales_comp1" : "someValue",
"sales_comp1_dos" : "someValue",
"sales_comp1_units" : "someValue",
"sales_comp1_NOI_unit" : "someValue",
"sales_comp1_sales_pr_unit" : "someValue",
"sales_comp1_adj_SPrice" : "someValue",
"sales_comp1_cap_rate" : "someValue",
"sales_comp2" : "someValue",
"sales_comp2_dos" : "someValue",
"sales_comp2_units" : "someValue",
"sales_comp2_NOI_unit" : "someValue",
"sales_comp2_sales_pr_unit" : "someValue",
"sales_comp2_adj_SPrice" : "someValue",
"sales_comp2_cap_rate" : "someValue",
"sales_comp3" : "someValue",
"sales_comp3_dos" : "someValue",
"sales_comp3_units" : "someValue",
"sales_comp3_NOI_unit" : "someValue",
"sales_comp3_sales_pr_unit" : "someValue",
"sales_comp3_adj_SPrice" : "someValue",
"sales_comp3_cap_rate" : "someValue"
}
我想将sales_compX值合并到一个名为salesComps的数组中:
{
"name" : "someValue",
"date" : "someValue",
"age" : "someValue",
"price" : "someValue",
"salesComps" : [
{
"sales_comp1" : "someValue",
"sales_comp1_dos" : "someValue",
"sales_comp1_units" : "someValue",
"sales_comp1_NOI_unit" : "someValue",
"sales_comp1_sales_pr_unit" : "someValue",
"sales_comp1_adj_SPrice" : "someValue",
"sales_comp1_cap_rate" : "someValue",
},
{
"sales_comp2" : "someValue",
"sales_comp2_dos" : "someValue",
"sales_comp2_units" : "someValue",
"sales_comp2_NOI_unit" : "someValue",
"sales_comp2_sales_pr_unit" : "someValue",
"sales_comp2_adj_SPrice" : "someValue",
"sales_comp2_cap_rate" : "someValue",
},
{
"sales_comp3" : "someValue",
"sales_comp3_dos" : "someValue",
"sales_comp3_units" : "someValue",
"sales_comp3_NOI_unit" : "someValue",
"sales_comp3_sales_pr_unit" : "someValue",
"sales_comp3_adj_SPrice" : "someValue",
"sales_comp3_cap_rate" : "someValue"
}
]
}
最简单的方法是什么?非常感谢Mongoose或Mongodb代码示例中的任何响应!
答案 0 :(得分:2)
首先,使用Object.keys()
循环访问数据,然后等待' sales_comp'数据突然出现。当它将键值对插入保持对象并从主数据中删除该条目时。完成后,将保持对象添加回数据中。像这样......
数据......
var data = {
"name" : "someValue",
"date" : "someValue",
"age" : "someValue",
"price" : "someValue",
"sales_comp1" : "someValue",
"sales_comp1_dos" : "someValue",
"sales_comp1_units" : "someValue",
"sales_comp1_NOI_unit" : "someValue",
"sales_comp1_sales_pr_unit" : "someValue",
"sales_comp1_adj_SPrice" : "someValue",
"sales_comp1_cap_rate" : "someValue",
"sales_comp2" : "someValue",
"sales_comp2_dos" : "someValue",
"sales_comp2_units" : "someValue",
"sales_comp2_NOI_unit" : "someValue",
"sales_comp2_sales_pr_unit" : "someValue",
"sales_comp2_adj_SPrice" : "someValue",
"sales_comp2_cap_rate" : "someValue",
"sales_comp3" : "someValue",
"sales_comp3_dos" : "someValue",
"sales_comp3_units" : "someValue",
"sales_comp3_NOI_unit" : "someValue",
"sales_comp3_sales_pr_unit" : "someValue",
"sales_comp3_adj_SPrice" : "someValue",
"sales_comp3_cap_rate" : "someValue"
};
代码......
// holding Object
var tmpStorage = {};
// Loop through the data
Object.keys(data).forEach(function(d) {
// look for 'sales_comp' keys
if (/sales_comp/.test(d)) {
// find which 'sales_comp' each 'd'
// belongs to with simple regex (allowing
// for more than single digits here)
var id = d.match(/sales_comp([\d]+)/)[1];
// create a tmp property for tmpStorage object
// if it doesn't exist (which it wont on the
// the first pass)
tmpStorage['tmp'+id] = tmpStorage['tmp'+id] || {};
// add the current key-value pair to the
// tmpStorage Object
tmpStorage['tmp'+id][d] = data[d];
// remove the current key-value pair from the
// data object
delete data[d]
}
});
'数据'对象现在看起来像这样......
console.log('data:',data);
/* =>
data: {
name: 'someValue',
date: 'someValue',
age: 'someValue',
price: 'someValue'
}
*/
tmpStorage对象看起来像这样......
console.log('tmpStorage:',tmpStorage);
/* =>
tmpStorage: {
tmp1: {
sales_comp1: 'someValue',
sales_comp1_dos: 'someValue',
sales_comp1_units: 'someValue',
sales_comp1_NOI_unit: 'someValue',
sales_comp1_sales_pr_unit: 'someValue',
sales_comp1_adj_SPrice: 'someValue',
sales_comp1_cap_rate: 'someValue'
},
tmp2: {
sales_comp2: 'someValue',
sales_comp2_dos: 'someValue',
sales_comp2_units: 'someValue',
sales_comp2_NOI_unit: 'someValue',
sales_comp2_sales_pr_unit: 'someValue',
sales_comp2_adj_SPrice: 'someValue',
sales_comp2_cap_rate: 'someValue'
},
tmp3: {
sales_comp3: 'someValue',
sales_comp3_dos: 'someValue',
sales_comp3_units: 'someValue',
sales_comp3_NOI_unit: 'someValue',
sales_comp3_sales_pr_unit: 'someValue',
sales_comp3_adj_SPrice: 'someValue',
sales_comp3_cap_rate: 'someValue'
}
}
*/
现在只需要推送“tmpStorage'进入一个新的" data.salesComps'阵列
data.salesComps = Object.keys(tmpStorage).map(function(t) {
return tmpStorage[t];
});
现在'数据'看起来像这样......
console.log('data:',data);
/* =>
data: {
name: 'someValue',
date: 'someValue',
age: 'someValue',
price: 'someValue',
salesComps: [
{ sales_comp1: 'someValue',
sales_comp1_dos: 'someValue',
sales_comp1_units: 'someValue',
sales_comp1_NOI_unit: 'someValue',
sales_comp1_sales_pr_unit: 'someValue',
sales_comp1_adj_SPrice: 'someValue',
sales_comp1_cap_rate: 'someValue'
},
{ sales_comp2: 'someValue',
sales_comp2_dos: 'someValue',
sales_comp2_units: 'someValue',
sales_comp2_NOI_unit: 'someValue',
sales_comp2_sales_pr_unit: 'someValue',
sales_comp2_adj_SPrice: 'someValue',
sales_comp2_cap_rate: 'someValue'
},
{ sales_comp3: 'someValue',
sales_comp3_dos: 'someValue',
sales_comp3_units: 'someValue',
sales_comp3_NOI_unit: 'someValue',
sales_comp3_sales_pr_unit: 'someValue',
sales_comp3_adj_SPrice: 'someValue',
sales_comp3_cap_rate: 'someValue'
}
]
}
*/
看起来可能看起来很复杂,但是一旦你拿出所有评论,你就会看到一个相对简单的两阶段过程 - 删除你需要的数据,然后以你想要的格式重新添加。
希望有所帮助:)
答案 1 :(得分:0)
一个关闭操作可能最好在mongo shell中完成,它具有处理此问题的JavaScript环境,而无需担心回调和承诺注意事项。
所以这里最好的做法是循环收集结果,并在将字段转换为数组后通过.bulkWrite()
方法重新写入集合:
var name = "collection";
var ops = [];
db.getCollection(name).find().forEach(doc => {
var obj = Object.keys(doc).filter(k => /^sales_comp/.test(k))
.map( k => ({ [k.match(/\d+/)[0]]: { [k.replace(/\d+/,"")]: doc[k] }}))
.reduce((acc,curr) => {
let a = Object.keys(curr)[0];
if ( !acc.hasOwnProperty(a) )
acc[a] = { };
acc[a][Object.keys(curr[a])[0]] = curr[a][Object.keys(curr[a])[0]];
return acc;
},{});
// Un-comment and swap if you don't want to retain the index number
//var comps = Object.keys(obj).map( k => obj[k] )
var comps = Object.keys(obj).map( k => Object.assign({ "index": parseInt(k) },obj[k]) );
var unset = Object.keys(doc).filter(k => /^sales_comp/.test(k))
.reduce((acc,curr) => Object.assign(acc,({ [curr]: 1 })),{});
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$unset": unset,
"$set": { "salesComps": comps }
}
}
});
if ( ops.length >= 500 ) {
db.getCollection(name).bulkWrite(ops);
ops = [];
}
});
if ( ops.length > 0 ) {
db.getCollection(name).bulkWrite(ops);
ops = [];
}
哪个会重写每个文档,如:
{
"_id" : ObjectId("5954461a38470d375d40aca1"),
"name" : "someValue",
"date" : "someValue",
"age" : "someValue",
"price" : "someValue",
"salesComps" : [
{
"index" : 1,
"sales_comp" : "someValue",
"sales_comp_dos" : "someValue",
"sales_comp_units" : "someValue",
"sales_comp_NOI_unit" : "someValue",
"sales_comp_sales_pr_unit" : "someValue",
"sales_comp_adj_SPrice" : "someValue",
"sales_comp_cap_rate" : "someValue"
},
{
"index" : 2,
"sales_comp" : "someValue",
"sales_comp_dos" : "someValue",
"sales_comp_units" : "someValue",
"sales_comp_NOI_unit" : "someValue",
"sales_comp_sales_pr_unit" : "someValue",
"sales_comp_adj_SPrice" : "someValue",
"sales_comp_cap_rate" : "someValue"
},
{
"index" : 3,
"sales_comp" : "someValue",
"sales_comp_dos" : "someValue",
"sales_comp_units" : "someValue",
"sales_comp_NOI_unit" : "someValue",
"sales_comp_sales_pr_unit" : "someValue",
"sales_comp_adj_SPrice" : "someValue",
"sales_comp_cap_rate" : "someValue"
}
]
}
这基本上是检查文档中是否以"sales_comp"
开头的“键”的名称,并在根据字符串的数字部分累积键并从名称中删除后,数据转换为每个不同数值的数组。
当实际处理目标集合的“更新”时,我们在以"sales_comp
开头的字段上使用$unset
运算符从文档中删除这些字段。然后我们使用$set
运算符和转换后的数组来创建新属性。
使用.map()
,.reduce()
和.filter()
时,您应该熟悉使用JavaScript时的数据结构,这里有一些常见的习语。