我如何使node.js MongoDB遵循对象引用

How do I make node.js MongoDB follow object references?

本文关键字:对象引用 MongoDB js 何使 node      更新时间:2023-09-26

此问题无效。

请看我的评论


当你在javascript中使用多维数组构建一个复杂的对象时,MongoDB不存储任何在技术上是引用的数组。MongoDB不按照引用将数据存储在文档中。

有办法强制这个吗?


例如,一个object包含一个array称为products。每个产品都有一个名为suppliers的数组。每个供应商都有一个名为shipments的数组。

这个对象是动态创建的,因此子数组是对父对象中实际数组的引用(javascript设计)。

MongoDB只存储第一个数组,忽略子域。

要解决这个问题,我必须克隆整个对象。例:jQuery.extend(true, {}, object);。但这可能需要一秒钟,这是一个很长的时间,我觉得这是不必要的。

我怎么能把这个对象与它的引用到MongoDB?是否有更快的方法克隆对象并删除引用?还有其他解决办法吗?

我正在寻找具体这种情况。而不是关于如何重组我的数据的想法。


在内部,javascript创建了对每个数组或对象的引用。如果你把那个数组赋值给一个对象,内存引用也会被赋值;不是实际内容

object

{
    a : 33,
    lot : 52,
    of : true,
    data : false,
    products : [Array] (id=115)
}

products

products : [
    {
        more : true,
        data : false,
        suppliers : [Array] (id=612)
    },
    {},
    {},
    //...
]

suppliers

suppliers : [
    {
        even : null,
        more : 52,
        data : false,
        shipments : [Array] (id=854)
    },
    {},
    {},
    //...
]

等。

第一个数组被插入到MongoDB;其余的都不见了。

在扁平化(jQuery.extend)之后,像这样:

{
    a : 33,
    lot : 52,
    of : true,
    data : false,
    products : [
        {
            more : true,
            data : false,
            suppliers : [
                {
                    even : null,
                    more : 52,
                    data : false,
                    shipments : [
                        {
                            some : 'foo',
                            more : 'bar',
                            data : false
                        },
                        {},
                        {},
                        //...
                    ]
                },
                {},
                {},
                //...
            ]
        },
        {},
        {},
        //...
    ],
}

文档插入到MongoDB没有问题

这是浅拷贝和深拷贝的问题。

虽然您可以在运行时遍历对象中的每个键并检查数组(或数组的数组等),但这可能不是性能最好的方法。如果你已经知道你的对象结构,那么你应该能够构建一个深度拷贝。

function Foo() {
     this.prop = "someKey";
     this.arr2d = [[0],[1],[2]];
}
Foo.prototype.getDeepCopy = function() {
    var self = this;
    return {
        prop: self.prop,
        arr2d: function() {
            var arr = [];
            for ( var i = 0; i < self.arr2d.length; i++ ) {
                var _a = [];
                for ( var j = 0; j < self.arr2d[i].length; j++ ) {
                    _a[j] = self.arr2d[i][j];
                }
                arr[i] = _a;
            }
            return arr;
        }()
    };
}

你也可以用一个接受对象引用或字面量的函数来代替使用原型。

function deepCopy(obj) {
    return {
        prop:obj.prop,
        arr2d:function() {...}()
    };
}

深度复制仍然需要遍历对象结构,但它将比

快。
var copy = JSON.parse(JSON.stringify(obj));

编辑:在不清楚的情况下,你将不得不建立一个没有引用的数据——这意味着要么通过深度拷贝重建它,要么首先从字面上构建它。

这个问题无效。MongoDB遵循引用。我无法编写一个脚本来重现这种行为。

我在我的主应用程序中发现了这个行为。管道中有几个承诺,要存储的对象会被更改。删除一些数组。

因为我没有等待MongoDB回调(因为写入失败并不意味着进程的其余部分不应该继续),显然,在MongoDB开始将其写入数据库之前,引用的对象被改变了。

在调试时,这完全超出了我的参考框架。我认为每个承诺的步骤将在事件循环的下一个刻度上执行。我假设节点MongoDB模块将在几个刻度之后更改之前将数据传递给适配器。

我需要启用写关注,并仅在回调启动后继续处理对象。这需要更长的时间,但我不需要克隆对象,这样可以节省时间。