javascript - 如何动态更新mongodb中的嵌套对象
问题描述
我们有一些任意嵌套的配置存储在 mongodb 中。
- 假设我们最初将以下对象存储在 mongodb 中。
const value = { 'a': { 'b': 1 } }
collection.insertOne({userId, value})
现在我想通过添加来修改数据库中的对象
const addValue = { 'f': { 'c': 2 } }
并且类似地有更多的嵌套对象。
const addValue1 = { 'a': { 'd': 1 }, 'f': { 'g': 1 } };
正如我们添加的那样,这些keys
是非常动态的,应该能够更新数据库中的值但不能替换它,所以期望存储的最终结果应该是
const result = collection.findOne({ userId });
console.log(result);
{ 'a': { 'b': 1, 'd': 1 }, 'f': { 'g': 1, 'c': 2 } }
如果 udpate 值为
const addValue2 = { 'a': { 'b' : { 'e': 1 } } }
预期的结果是
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: {} }`
使用的删除方法
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 });
}
});
});
}
解决方案
这里的困难是你必须将你的对象转换成 MongoDB 的点符号,它可以用来构建你的更新语句。您可以通过运行以下函数来做到这一点:
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 });
您不能直接在对象上运行$set的原因是它将替换现有的a
嵌套对象而不是合并它。
推荐阅读
- go - 将无限字节写入 bytes.Buffer
- spring - 春天云网关
- angular - Angular 6 Scroll Listener 重新加载组件
- python - Tensorflow:识别 MultiRNN 中的最终状态
- amazon-web-services - 我一直从 AWS 上的 EIP 收费
- haskell - (<*>) :: f (a -> b) -> fa -> fb 在 Functor 类中到底做了什么
- java - 在非模拟方法中模拟方法
- ios - URLSession 在 WfI 上是否安全?
- php - Symfony 3 在根目录下提供静态 html 文件
- python-3.x - 用`statsmodels`绘制掩码值的残差