[英]how to dynamically update the nested objects in mongodb
We have some arbitrarily nested configuration that we store in the mongodb.我们有一些任意嵌套的配置存储在 mongodb 中。
const value = { 'a': { 'b': 1 } }
collection.insertOne({userId, value})
now I want to modify the object in the database by adding现在我想通过添加来修改数据库中的对象
const addValue = { 'f': { 'c': 2 } }
and similarly with few more nested object.类似的还有更多的嵌套对象。
const addValue1 = { 'a': { 'd': 1 }, 'f': { 'g': 1 } };
As we adding, these keys
are very dynacmic and should able to update value in the db but not replace it, so expecting the end result stored should be正如我们添加的那样,这些
keys
是非常动态的,应该能够更新数据库中的值但不能替换它,因此期望存储的最终结果应该是
const result = collection.findOne({ userId });
console.log(result);
{ 'a': { 'b': 1, 'd': 1 }, 'f': { 'g': 1, 'c': 2 } }
And also overwrite if the udpate value is如果 udpate 值为
const addValue2 = { 'a': { 'b' : { 'e': 1 } } }
expected result is预期结果是
const result2 = { 'a': { 'b': { 'e': 1 } , 'd': 1 }, 'f': { 'g': 1, 'c': 2 } }
let testObject = new MongoDBStorageService('test', dbConnection as any, 'userTestSchema');
testObject.load({ 'a': { 'b': 1 }});
testObject.removeValue('a.b');
const content = await testObject.contents;
expect(content).toEqual({}); // but we see output as `{ a: {} }`
Remove method used使用的删除方法
public async removeValue(key: string) {
return await this.remove(JSON.parse(`{\"${key}\": "" }`));
}
private remove(value) {
return new Promise((resolve, reject) => {
this.collection.updateOne({ user: this.userId }, {
$unset: value,
}, { upsert: false }, function (err, res) {
if (err) {
reject(err);
} else {
console.log('REUSLL AFTER REMOVE', res.);
resolve({ id: true });
}
});
});
}
The difficulty here is that you have to convert your objects into MongoDB's dot notation which can be used to build your update statements.这里的困难在于您必须将对象转换为 MongoDB 的点表示法,它可用于构建更新语句。 You can do that by running below function:
您可以通过运行以下函数来做到这一点:
let flatten = (obj, prefix, result) => { result = result || {}; for(let key of Object.keys(obj)){ let keyExpr = prefix ? `${prefix}.${key}` : `${key}`; if(typeof obj[key] === "object"){ flatten(obj[key], keyExpr, result); } else { result[keyExpr] = obj[key]; } } return result; } const addValue = { 'f': { 'c': 2 } } let update1 = flatten(addValue) console.log(update1); const addValue1 = { 'a': { 'd': 1 }, 'f': { 'g': 1 } }; let update2 = flatten(addValue1); console.log(update2);
const value = { 'a': { 'b': 1 } }
const userId = 1;
db.col.insertOne({userId, ...value})
db.col.update({ userId: userId }, { $set: update1 });
db.col.update({ userId: userId }, { $set: update2 });
The reason why you can't run $set directly on your objects is that it will replace existing a
nested object instead of merging it.不能直接在对象上运行$set的原因是它将替换现有
a
嵌套对象而不是合并它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.