保存后自动填充子文档

c1m*_*ore 4 mongoose

我想在自动保存特定模型后始终填充子文档。我真正想要的是以下内容:

MyModel.post('save', function(doc, next) {
    doc.populate('path').then(next);
});
Run Code Online (Sandbox Code Playgroud)

但是,上述方法不起作用,因为

post中间件不直接接收流控制,例如没有nextdone回调传递给它。post钩子是为这些方法注册传统事件侦听器的一种方式。

当然,有“异步 Post Hooks”,但它们仍然不接收控制流,因此无法保证在我需要时会填充子文档。

为什么不直接使用嵌入式文档?对于这种情况,子文档与父文档相同(例如,我使用的是 Composite 模式之类的东西),这会导致我不确定如何解决(或者我是否可以解决)的循环依赖. 对于其他情况,我可能希望能够在不通过父文档的情况下访问子文档。

我考虑的另一种方法是:

const nativeSave = /* ? */;

MyModel.methods.save = function save() {
    return nativeSave.call(this).then(function(savedDoc) {
        return savedDoc.populate('path');
    });
};
Run Code Online (Sandbox Code Playgroud)

然而,这有两个问题。首先,这似乎是一个迂回的解决方案。如果有一种更原生的方法不违背猫鼬的实现,我会更喜欢那个。其次,我不知道我会设置什么nativeSave(如 所示/* ? */)。

那么,对于获得这种行为有哪些建议呢?如果我的第二个解决方案对当前版本的猫鼬来说是最好的,我应该设置nativeSave什么?我已经考虑过嵌入文档,所以除非您提供有关解决循环依赖的建议,否则请不要建议使用它们。即便如此,我还是想要针对我提到的其他用例的解决方案。

正如我在评论中所解释的,这与按照其他帖子的要求保存后手动填充子文档不同。我希望这会自动发生以避免泄露我的实现细节(例如使用 ObjectIds 而不是真实文档)。

Rob*_*kal 6

我要说的是,即使可以对内置的猫鼬方法(如“ save ”或“ find ”)进行猴子修补,这也可能是一个糟糕的主意。除了并非对 save 方法的每次调用都需要产生额外 populate 调用的开销这一事实之外,您当然不想通过下降到底层 mongo 驱动程序来改变函数的工作方式(您失去了验证,生命循环方法,如果你想使用猫鼬文档,你必须重新查询数据库)。

你冒着巨大的风险破坏任何依赖于“保存”以某种方式工作的代码。各种各样的插件都被排除在外,你可能会让任何追随你的开发人员感到惊讶。我不会在我负责的代码库中允许它。

因此,您只能创建静态或模式方法。在该方法中,您将调用 save,然后调用 populate。像这样的东西:

MyModel.methods.saveAndPopulate = function(doc) {
  return doc.save().then(doc => doc.populate('foo').execPopulate())
}
Run Code Online (Sandbox Code Playgroud)

这几乎是这里建议的最新方法:Mongoose populate after save。这就是为什么我投票结束你的问题。