Javascript 如何动态更新mongodb中的嵌套对象

Javascript 如何动态更新mongodb中的嵌套对象,javascript,mongodb,mongodb-query,Javascript,Mongodb,Mongodb Query,我们在mongodb中存储了一些任意嵌套的配置 假设我们最初将以下对象存储在mongodb中 现在我想通过添加 const addValue = { 'f': { 'c': 2 } } 类似地,很少有嵌套对象 const addValue1 = { 'a': { 'd': 1 }, 'f': { 'g': 1 } }; 正如我们所添加的,这些键是非常动态的,应该能够更新数据库中的值,但不能替换它,因此期望存储的最终结果应该是 const result = collection.findOne

我们在mongodb中存储了一些任意嵌套的配置

  • 假设我们最初将以下对象存储在mongodb中 现在我想通过添加

    const addValue = { 'f': { 'c': 2 } }
    
    类似地,很少有嵌套对象

    const addValue1 = { 'a': { 'd': 1 }, 'f': { 'g': 1 } };
    
    正如我们所添加的,这些
    键是非常动态的,应该能够更新数据库中的值,但不能替换它,因此期望存储的最终结果应该是

    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 } }
    
    
    删除时也是如此 删除所使用的方法

    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的点表示法,该点表示法可用于构建update语句。您可以通过运行以下函数来完成此操作:

    let flatten=(对象、前缀、结果)=>{
    结果=结果|{};
    for(对象的let键。键(obj)){
    让keyExpr=prefix?`${prefix}.${key}`:`${key}`;
    if(对象类型[键]=“对象”){
    展平(obj[key],keyExpr,result);
    }否则{
    结果[keyExpr]=obj[key];
    }
    }
    返回结果;
    }
    常量addValue={f':{c':2}
    让update1=展平(addValue)
    console.log(update1);
    常量addValue1={'a':{'d':1},'f':{'g':1};
    让update2=展平(addValue1);
    
    console.log(update2)这里的困难在于必须将对象转换为MongoDB的点表示法,该点表示法可用于构建update语句。您可以通过运行以下函数来完成此操作:

    let flatten=(对象、前缀、结果)=>{
    结果=结果|{};
    for(对象的let键。键(obj)){
    让keyExpr=prefix?`${prefix}.${key}`:`${key}`;
    if(对象类型[键]=“对象”){
    展平(obj[key],keyExpr,result);
    }否则{
    结果[keyExpr]=obj[key];
    }
    }
    返回结果;
    }
    常量addValue={f':{c':2}
    让update1=展平(addValue)
    console.log(update1);
    常量addValue1={'a':{'d':1},'f':{'g':1};
    让update2=展平(addValue1);
    
    console.log(update2)有意义让我快速测试it@user1595858测试进行得怎么样:)?很好地添加了值。但是在删除方面有问题。@user1595858最初没有提到有任何删除。稍后我可以看一下:-)@user1595858关于您的删除示例:每当您运行
    updateOne
    时,您都不知道
    a
    字段的状态。您只需取消设置您知道的是
    a.b
    的密钥,但不知道是否有
    a.c
    a.d
    等。您所能做的就是运行
    $unset
    并稍后以某种方式处理空对象。或者,您需要先
    查找
    文档,然后运行更新,知道它的全部内容-但这是两次数据库往返,所以您可以决定哪种方式更可取。有意义让我快速测试一下it@user1595858测试进行得怎么样:)?很好地添加了值。但是在删除方面有问题。@user1595858最初没有提到有任何删除。稍后我可以看一下:-)@user1595858关于您的删除示例:每当您运行
    updateOne
    时,您都不知道
    a
    字段的状态。您只需取消设置您知道的是
    a.b
    的密钥,但不知道是否有
    a.c
    a.d
    等。您所能做的就是运行
    $unset
    并稍后以某种方式处理空对象。或者,您需要先
    查找
    文档,然后运行update,知道它的全部内容-但这是两次数据库往返,因此您可以决定采用哪种方式。
    
        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 });
                }
            });
        });
    }