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

时间:2015-10-07 19:37:40

标签: javascript arrays node.js mongodb reference

此问题无效。

请参阅my comment

当您在javascript中使用多维数组构建复杂对象时,MongoDB不存储任何技术上是引用的数组。 MongoDB不遵循引用并将数据存储在文档中。

有没有办法强迫这个?

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

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

只有第一个数组存储在MongoDB中,子域将被忽略。

要解决这个问题,我必须克隆整个对象。例如:shipments。但这可能需要一秒钟,这是很长一段时间,我觉得它没有必要。

如何将此对象与MongoDB中的引用一起提供?有没有更快的方法来克隆对象并删除引用?还有其他解决方案吗?

我正在寻找具体的方案。不是关于如何重组我的数据的想法。

在内部,javascript创建对每个创建的数组或对象的引用。如果将该数组分配给对象值,则会分配内存引用;不是实际的内容。

主要jQuery.extend(true, {}, object);

object

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

products

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

suppliers

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

展平后(jQuery.extend),像这样:

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

文档会毫无问题地插入到MongoDB中。

2 个答案:

答案 0 :(得分:0)

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

虽然您可以在运行时迭代对象中的每个键并检查数组(或数组数组等),但这可能不是最高效的。如果您已经知道对象结构,那么您应该能够构建一个深层副本。

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));

编辑:如果不清楚,你将不得不建立一个没有引用的数据 - 这意味着要么通过深层复制重建它,要么首先在字面上构建它。

答案 1 :(得分:0)

这个问题无效。 MongoDB确实遵循了引用。我无法创建一个再现此行为的脚本。

我在主应用程序中发现了这一点,我目睹了这种行为。在管道中有一些承诺,待存储的对象被改变了。删除一些数组。

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

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

我需要启用写入问题,并且只有在启动回调后才继续使用该对象。这需要更长的时间,但我不必克隆对象,这样可以节省时间。