猫鼬:设置双向引用

tsu*_*ino 2 mongoose mongodb node.js

我正在开发一个Express + Mongoose网络应用程序,它有许多相互依赖的模型.除非我可能没有正确设计我的数据,否则我希望找出在两个彼此相关的对象之间设置引用的最佳方法.

我知道在我的Schema obj中,如果我想让Schema引用另一个Schema,我会添加referenceId: { type: Schema.Types.ObjectId, ref: 'ModelName' },为一个属性.到目前为止,在创建模型时,我一直在将此属性设置为id我想要引用的属性.例如:obj.referenceId = someReferenceId; obj.save(...).

但是,如果我有两个独立的模式但每个模式彼此都有引用怎么办?设置这些的最佳方法是什么?

现在,我正在执行以下操作,但代码看起来非常混乱:

objectASchema = Schema({
    objectBReference: { type: Schema.Types.ObjectId, ref: 'ObjectB' },
})
mongoose.model('ObjectA', objectASchema);

objectBSchema = Schema({
    objectAReference: { type: Schema.Types.ObjectId, ref: 'ObjectA' },
})
mongoose.model('ObjectB', objectBSchema);

// in a route/controller, and assuming we have an Object B created
// but you can see that if I don't have that, it gets messier
ObjectA.create(..., function(err, objectA) {
    objectA.objectBReference = objectBReferenceId;
    objectA.save(function(err) {
        ...
        ObjectB.findById({_id: objectBReferenceId}, function(err, objectB) {
            objectB.objectAReference = objectA._id;
            objectB.save(function(err) {
                if (!err) {
                    // success! we're done here...
                }
            });
        })
    });
})
Run Code Online (Sandbox Code Playgroud)

我故意避免嵌入这种情况,因为在我的应用程序中,我在假设我需要单独查询这些对象而不必从其中加载数据的情况下运行.

我的用例类似于a Product,ReviewUsermodel 这样的东西,其中每个引用另一个,但不一定嵌入另一个.查询可以是:获取此产品的所有评论或该用户的所有评论.这意味着评论不能嵌入用户或产品中.

Jas*_*ust 6

使用MongooseJS,您可以在本地创建它们,关联它们,然后使用promise将这两者并行保存到数据库中(这使用本机Promise对象,但库可以工作):

var objectA = new ObjectA();
var objectB = new ObjectB();

objectA.objectBReference = objectB;
objectB.objectAReference = objectA;

Promise.all([
  objectA.save(),
  objectB.save()
]).then(function(savedObjects) {
  // Do something to celebrate?
}).catch(function(err) {
  // one or both errored
});
Run Code Online (Sandbox Code Playgroud)

更新:如果需要,您还可以使用嵌套保存.关键点在于ID是在本地生成的,可以与其他文档关联,而无需先保存.

var objectA = new ObjectA();
var objectB = new ObjectB();

objectA.objectBReference = objectB;
objectB.objectAReference = objectA;

objectA.save(function (err, objA) {
  if (err) { ... }

  objectB.save(function (err, objB) {
    if (err) { ... }

    // Do something to celebrate?
  });
});
Run Code Online (Sandbox Code Playgroud)