我可以通过虚拟填充过滤 mongo 查询吗?

问题描述 投票:0回答:1

我在房产模型和销售模型之间有父级参考关系。在我的销售模型中,我包含一个引用父属性的字段:

property: {
      type: mongoose.Schema.ObjectId,
      ref: "Property",
      required: [true, "Sale must belong to a property"],
    }

在我的销售模型的最后,我包含了一个 mongoose 预查找中间件来填充引用属性的名称,以便可以在查询中对其进行过滤:

saleSchema.pre(/^find/, function (next) {
  this.populate({
    path: "property",
    select: "propInfo.propName",
  });
  next();
});

我想向我的销售路由器提交请求以退回仅适用于该房产名称的销售:

{{URL}}api/v1/sales?property.propInfo.propName=SampleName

当我向 {{URL}}api/v1/sales 发送 getAll 请求且参数中没有任何过滤器时,所有属性名称都将填充在响应中。

但是,每当我尝试按虚拟填充属性名称进行过滤或查询时,它都不会返回任何内容。看起来好像 Mongo 在查询后填充了父属性的字段,即使我有一个预查找中间件来填充虚拟值。

任何帮助或指导将不胜感激。

mongoose mongodb-query mongoose-schema mongoose-populate mongoose-web-server
1个回答
0
投票

这是一个非常好的问题,但却是常见的误解。不幸的是,在这种情况下,

pre
钩子populate
方法附加到
find
方法。因此,您无法查询填充的字段,因为在查询执行之前它们不会被添加。

使用 mongoose

populate

,你无法根据子文档的查询条件过滤父文档。这是限制之一。

值得庆幸的是,猫鼬模型有

Model.aggregate()

 方法,这种事情非常简单。

在下面的示例中,我假设您有

sales

 集合和基于您的 
properties
Sale
 型号名称的 
Property
 集合。我还添加了一些额外的随机字段,例如 
name
size
 只是为了说明。

  1. $lookup
    :这与 
    populate
     相同,其中针对 
    properties
     集合进行查找,以将 
    Sales.property
     字段与 
    Property._id
     字段进行匹配。
  2. $unwind
    :将数组从
    $lookup
    变成对象。
  3. $match
    :现在您可以使用 
    propName
     查询 
    SampleName
  4. $project
    :只输出你想要的字段。
const sales = await Sale.aggregate([ { $lookup: { from: "properties", localField: "property", foreignField: "_id", as: "property" } }, { $unwind: "$property" }, { $match: { "property.propInfo.propName": SampleName } }, { $project: { "name": 1, "property.propInfo.propName": 1, "size": 1 } } ])
请参阅

此处了解包含一些测试数据的工作示例。

© www.soinside.com 2019 - 2024. All rights reserved.