You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中Mongoose嵌套Label的Product查询返回空数组问题

问题:查询关联Label名称为'Something'的Product返回空数组

我在Product文档中关联了Label文档,尝试用以下代码查询所有Label名称为'Something'的Product文档,但返回结果是空数组:

return this.productModel.find({
      'label.name': 'Something',
    });

以下是LabelSchema.ts和ProductSchema.ts的定义:

LabelSchema.ts

@Schema({ versionKey: false, timestamps: true })
export class Label extends Document {
  @Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true })
  user: User;

  @Prop({ type: String, required: true })
  name: string;

  @Prop({ type: String, default: null })
  email: string | null;

  @Prop({ type: String, default: null })
  description: string;

  @Prop({ type: SocialSchema, default: new Social() })
  socials: Social;

  @Prop({ type: String, enum: LabelStatus, default: LabelStatus.Draft })
  status: string;

  // TODO add FILE document
  @Prop({ type: String, default: null })
  avatar: any;

  // TODO add FILE document
  @Prop({ type: String, default: null })
  header: any;

  @Prop({
    type: Number,
    default: process.env.APP_DEFAULT_COMMISSION_RATE,
  })
  commissionRate: number;

  @Prop({ type: Number, default: 0 })
  earnings: number;

  @Prop({ type: String, required: true })
  slug: string;

  @Prop({ type: Date, required: true })
  createdAt: Date;

  @Prop({ type: Date, required: true })
  updatedAt: Date;
}

ProductSchema.ts

@Schema({
  versionKey: false,
  timestamps: true,
})
export class Product extends Document {
  @Prop({ type: String, required: true })
  name: string;

  @Prop({ type: String, enum: ProductStatus, default: ProductStatus.Draft })
  status: string;

  @Prop({
    type: mongoose.Schema.Types.ObjectId,
    ref: Label.name,
    autopopulate: true,
  })
  label: Label;

  @Prop({ type: String, default: '' })
  shortDescription: string;

  @Prop({ type: String, default: '' })
  description: string;

  @Prop({ type: Number, default: null })
  price: number | null;

  @Prop({ type: Number, default: null })
  salePrice: number | null;

  @Prop({ type: Boolean, default: false })
  isFree: boolean;

  //TODO add FILE document
  artwork: any;

  //TODO add FILE document
  audioPreview: any;

  @Prop([
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Category.name,
      autopopulate: true,
    },
  ])
  category: Category[];

  @Prop({ type: Boolean, default: false })
  featured: false;

  @Prop({ type: String, required: true })
  slug: string;

  @Prop({ type: Date, required: true })
  createdAt: Date;

  @Prop({ type: Date, required: true })
  updatedAt: Date;
}

解决方案

问题原因

Product的label字段定义为mongoose.Schema.Types.ObjectId,是对Label文档的引用关系,数据库中存储的只是Label的ID值,并非完整的Label对象。因此直接通过'label.name'查询时,数据库中不存在这个字段路径,自然返回空数组。

方法一:先查Label ID再查Product

先找到名称为'Something'的Label的ID,再用该ID查询关联的Product:

// 第一步:获取目标Label的ID
const targetLabel = await this.labelModel.findOne({ name: 'Something' });
if (!targetLabel) {
  return [];
}
// 第二步:查询关联该Label的所有Product
return this.productModel.find({ label: targetLabel._id });

方法二:使用聚合管道关联查询

通过MongoDB的聚合$lookup操作,关联Label集合后再筛选符合条件的记录:

return this.productModel.aggregate([
  // 关联Label集合,将匹配的Label数据加入product文档
  {
    $lookup: {
      from: 'labels', // 注意这里是Label集合的实际名称,通常为模型名小写复数
      localField: 'label',
      foreignField: '_id',
      as: 'label'
    }
  },
  // 展开label数组(因为$lookup返回的是数组)
  { $unwind: '$label' },
  // 筛选label名称为'Something'的记录
  { $match: { 'label.name': 'Something' } }
]);

内容的提问来源于stack exchange,提问作者nerrood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:15:48