javascript - 仅当该字段包含 ObjectId 时,是否可以让 mongoose 填充混合字段?

标签 javascript node.js typescript mongoose mongoose-populate

设置

假设我们有 FooBar 的模式。 Foo 有一个字段 bar。此字段可以包含引用文档 Bar 的 ObjectId,也可以包含不是 ObjectId 的其他任意对象。

const fooSchema = new mongoose.Schema({
  bar: {
    type: mongoose.Schema.Types.Mixed,
    ref: 'Bar'
  }
});
const Foo = <any>mongoose.model<any>('Foo', fooSchema);

const barSchema = new mongoose.Schema({
  name: String
});
const Bar = <any>mongoose.model<any>('Bar', barSchema);

问题

现在假设我们有一堆 Foo 文档。

我希望能够使用 mongoose 的 populatebar 字段上自动将对 Bar 文档的引用替换为实际的 Bar 文档本身。我还想保留所有其他不是对 Bar 文档的引用的对象。

通常,我会使用类似这样的方法获取所有 Foo 文档,然后填充 bar 字段:

Foo.find().populate('bar')

但是,当遇到 bar 字段中不是 ObjectId 的对象时,此方法将抛出异常,而不是让它们保持不变。

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): CastError: Cast to ObjectId failed for value "Some arbitrary object" at path "_id" for model "Bar"

尝试寻找解决方案

我检查了在 populate 上使用 match 选项,要求 Bar 上存在一个字段:

Foo.find().populate({
  path: 'bar',
  match: {
    name: {
      $exists: true
    }
  }
}

不幸的是,错误是一样的。

问题

那么我的问题是,如果字段包含 ObjectId,是否有任何方法可以让 mongoose 仅​​填充该字段,否则就不管它?

最佳答案

据我所知,您不能以这种方式使用填充。 Select 属性在尝试获取 population 值后起作用,并且在此之前无法对其进行过滤。

您必须手动完成。您可以手动完成。

let foos = await Foo.find({});
foos = foos.map(function (f) {
  return new Promise(function (resolve) {
    if (condition()) {
        Foo.populate(f, {path: 'bar'}).then(function(populatedF){
            resolve(f);
        });
    } else {
      resolve(f);
    }
  });
});

await Promise.all(foos).then(function (fs) {
  res.status(200).json(fs);
});

优雅的做法是将其包装在模型的 post hook 或静态方法中。

另一种选择是发送 2 个查询:

const foosPopulated = Foo.find({ alma: { $type: 2 } }).populate('bar'); // type of string
const foosNotPopulated = Foo.find({ alma: { $type: 3 } }); // type of object

const foos = foosPopulated.concat(foosNotPopulated);

这当然不是最优的,因为有 2 个查询(和所有人口查询),但也许这对您来说不是问题。可读性要好得多。当然,您随后可以更改查找查询以专门匹配您的情况。

关于javascript - 仅当该字段包含 ObjectId 时,是否可以让 mongoose 填充混合字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46373989/

相关文章:

angular - 将 Ionic 应用程序添加到 Rails 4 应用程序

javascript - 什么是 __proto__ 以及为什么它总是在任何 JS 对象中出现并逐渐消失?

javascript - SetRequiredLevel 它是如何工作的?

javascript - 如何将 HTML 表格转换为图表?

javascript - 并行异步迭代器 - 有可能吗?

typescript - TS1109,WebStorm 对可选链接的 react 不正确

javascript - 单击表中的按钮会同时触发按钮和表事件

node.js - 如何在 npm 中本地安装和运行 Typescript?

mysql - Sequelize 4 - eagger 加载时属于多对多插入问题

javascript - 从 TypeScript 调用 JavaScript 函数