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

NestJS中Mongoose的populate失效及关联查询无结果问题排查

NestJS + Mongoose 关联查询异常问题

问题现象

在NestJS项目中使用Mongoose时遇到两个问题:

  • populate关联查询无法正常工作
  • 通过Night文档中teams数组的ObjectId查询Team集合时返回空数组

服务方法代码

async getTeamsByNightId(id: string) {
    const night = await this.nightModel.findById({_id: id});
    console.log('night: ', night);
    //@TODO Why is populate not working?
    //const night = (await this.nightModel.findById({_id: id})).populate('teams');

    if (night) {
      const teamIds = night.teams.map((teamId) => teamId.toString());
      console.log('teamIds: ', teamIds);
      try {
        const teams = await this.teamModel.find({ _id: { $in: night.teams } }).exec();
        console.log('teams: ', teams);
      } catch (error) {
        console.log(error);
      }
      
    } else {
      throw new NotFoundException('No matching Night found');
    }
  }

控制台输出

Mongoose: nights.findOne({ _id: ObjectId("6552ad936a93bab2b686496d") }, {})
night:  {
  _id: new ObjectId("6552ad936a93bab2b686496d"),
  name: 'a',
  askedQuestions: [],
  teams: [ new ObjectId("6552ada76a93bab2b6864972") ],
  password: '487254',
  __v: 1
}
teamIds:  [ '6552ada76a93bab2b6864972' ]
Mongoose: teams.find({ _id: { '$in': [ ObjectId("6552ada76a93bab2b6864972") ] } }, {})
teams:  []

Schema定义

Night Schema

import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { HydratedDocument, Types } from "mongoose";

export type NightDocument = HydratedDocument<Night>;

@Schema()
export class Night {
    @Prop()
    name: string;

    @Prop()
    password: string;

    @Prop([{ type: Types.ObjectId, ref: 'Question' }])
    askedQuestions: Types.ObjectId[];

    @Prop([{ type: Types.ObjectId, ref: 'Team' }])
    teams: Types.ObjectId[];;
}

export const NightSchema = SchemaFactory.createForClass(Night);

Team Schema

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument, Types } from 'mongoose';

export type TeamDocument = HydratedDocument<Team>;

@Schema()
export class Team {

  @Prop()
  username: string;

  @Prop()
  password: string;
}

export const TeamSchema = SchemaFactory.createForClass(Team);

添加Team到Night的方法

async addTeamToNight(teamId: string, addTeamToNightDTO: AddTeamToNightDTO) {
    const name = addTeamToNightDTO.name;
    const password = addTeamToNightDTO.password;
    const night = await this.nightModel.findOne({name, password}).exec();

    if (night) {
      night.teams.push(new Types.ObjectId(teamId));
      return await night.save();
    } else {
      throw new NotFoundException('Name or Password incorrect');
    }
  }

疑问

请问我哪里操作出错了?


问题原因及解决方案

1. 查询Team返回空数组的原因

你存入Night的teamId对应的文档很可能不存在于Team集合中。可以直接在MongoDB客户端执行db.teams.find({_id: ObjectId("6552ada76a93bab2b6864972")}),验证该ObjectId是否真的对应一个Team文档。另外,检查传入addTeamToNight的teamId是否正确,有没有拼写或格式错误。

2. populate失效的原因

你写的(await this.nightModel.findById({_id: id})).populate('teams')写法错误,Mongoose的populate需要在查询链中调用,或者对已查询的文档执行execPopulate()。正确写法有两种:

  • 链式调用(推荐):
    const night = await this.nightModel.findById(id).populate('teams').exec();
    
  • 对已获取的文档执行:
    const night = await this.nightModel.findById(id);
    await night.populate('teams');
    

3. 额外修复点

  • Night Schema中teams字段多了一个分号,修正为:teams: Types.ObjectId[];
  • 在addTeamToNight方法中,建议先验证teamId对应的Team是否存在,再添加到Night的teams数组,避免存入无效ObjectId:
    async addTeamToNight(teamId: string, addTeamToNightDTO: AddTeamToNightDTO) {
      const name = addTeamToNightDTO.name;
      const password = addTeamToNightDTO.password;
      
      // 先验证Team存在
      const teamExists = await this.teamModel.exists({_id: teamId});
      if (!teamExists) {
        throw new NotFoundException('Team not found');
      }
      
      const night = await this.nightModel.findOne({name, password}).exec();
      if (night) {
        night.teams.push(new Types.ObjectId(teamId));
        return await night.save();
      } else {
        throw new NotFoundException('Name or Password incorrect');
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:44:56