mongoose Mongodb填充不带模型参数

rsaldnfx  于 5个月前  发布在  Go
关注(0)|答案(1)|浏览(47)

我试图在另一个集合中填充某个集合。但是,如果没有在populate方法中指定model,它就不会替换为实际文档。

  • cabinet.schema.ts*
import {Prop, Schema, SchemaFactory} from '@nestjs/mongoose';
import { Date, HydratedDocument, Model, Schema as MongooseSchema } from 'mongoose';

export type CabinetDocument = HydratedDocument<Cabinet>;

export const CabinetProjection = {
    _id: false,
    __v: false,
}

@Schema()
export class Cabinet {

    @Prop({
        required: true,
        unique: true
    })
    id: string;

    @Prop()
    items: [{
        item: { type: MongooseSchema.Types.ObjectId, ref: "Item" },
        status: string;
        amount: number;
    }];
}

export const CabinetSchema = SchemaFactory.createForClass(Cabinet)

字符串

  • item.schema.ts*
import {Prop, Schema, SchemaFactory} from '@nestjs/mongoose';
import mongoose, { HydratedDocument } from 'mongoose';

export type ItemDocument = HydratedDocument<Item>;

export const ItemProjection = {
    _id: false,
    __v: false,
}

@Schema()
export class Item {

    @Prop({
        required: true,
        unique: true
    })
    qId: string;

    @Prop()
    name: string;

    @Prop()
    description: string;
}

export const ItemSchema = SchemaFactory.createForClass(Item)

  • cabinet.service.ts*
import { Injectable } from '@nestjs/common';
import { CreateCabinetDto } from './dto/create-cabinet.dto';
import { UpdateCabinetDto } from './dto/update-cabinet.dto';
import { Cabinet, CabinetProjection, CabinetSchema } from './schemas/cabinet.schema';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';

@Injectable()
export class CabinetService {

  constructor(@InjectModel(Cabinet.name) private cabinetModel: Model<Cabinet>) {}

  async findOne(id: string): Promise<Cabinet> {

    const result = this.cabinetModel.findOne({
      id: id,
    }, CabinetProjection).populate({path: "items.item", model: "Item"}).exec();

    return result;
  }
}


在这个设置下,它工作得很好,但是如果我删除model: "Item",而不是填充Item文档,我看到的是对象引用。ref: "Item"参数不够吗?
我的收藏名称也是橱柜物品

  • 编辑:**

显然问题出在Cabinet的类结构上。如果我修改下面的代码,它就可以在没有模型参数的情况下工作了。如果有任何解释,我将不胜感激。

@Schema()
export class Cabinet {

    @Prop({
        required: true,
        unique: true
    })
    id: string;

    @Prop({ type: [CabinetItem]  })
    items: CabinetItem[];
}

@Schema()
export class CabinetItem{

    @Prop({ type: MongooseSchema.Types.ObjectId, ref: Item.name })
    item: Item,
    
    @Prop()
    status: string;
    
    @Prop()
    amount: number;
}

z8dt9xmd

z8dt9xmd1#

当我和开发人员一起使用mongoose时,这是最大的困惑之一。希望这能解释。
当我在schema属性上设置ref时,我需要指定我希望mongoose使用的模型来执行populate,并将所有ObjectId替换为引用集合中的实际文档。
下面是一个简单的用户听歌曲的例子:

// User.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
    name: String,
    songs: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Song'
    }]
})
const User = mongoose.model("User", userSchema);
export default User;
// Song.js
import mongoose from 'mongoose';
const songSchema = new mongoose.Schema({
    title: String,
    artist: String
})
const Song = mongoose.model("Song", songSchema);
export default Song;
import mongoose from 'mongoose';
import User from "../models/User.js";
import Song from "../models/Song.js";
mongoose.connect('mongodb://127.0.0.1:27017/myapp').then(()=>{
   User.find().populate('songs').then(users =>{
      console.log(users);
   });
});
  1. Mongoose将模型名称Map到集合名称。这意味着当我创建模型时,mongoose会查找该函数中第一个参数的复数形式:
mongoose.model("User", userSchema);
// "User" model --> "users" collection
mongoose.model("Song", songSchema);
// "Song" model --> "songs" collection

  1. Mongoose现在有2个模型注册,它知道:
console.log(mongoose.connection.models);
{
  User: Model { User },
  Song: Model { Song },
}


1.当我尝试populate时,所有的User.songs mongoose将首先查看populate方法的options对象中的model参数。如果没有,则将使用模式中的ref值来查找要使用的模型。

User.find().populate('songs');
// You want to populate 'songs' huh? 
// There is no options object such as {path: 'songs', model: 'Song'}
// Let me look at your schema for 'songs':
songs: [{
   type: mongoose.Schema.Types.ObjectId,
   ref: 'Song' //< Bingo
}]
// I have found the model you want me to use. It's 'Song', thank you!

  1. Mongoose现在将在mongoose.connection.models中查找Song模型,现在可以使用它来执行populate。在后台,它使用称为modelNamesFromRefPathgetModelsMapForPopulate的函数。
    1.这里的关键是连接。不同的连接可以注册不同的模型。为了让上面的populate工作,UserSong模型都需要在同一个连接上注册。在我的例子中,我使用了默认的mongoose.connect连接,所以我的两个模型都注册在mongoose.connection.models上。然而,有些库使用mongoose.createConnection,并在一个连接上注册一个模型,在另一个连接上注册另一个模型。在这种情况下,您必须将实际模型而不仅仅是模型名称作为参数传递给populate,如下所示:
User.find().populate({path:'songs', model: Song});


所以为了回答你的问题“* ref:“Item”参数不够吗?*",是的,这是足够的,通常情况下,可能是在运行populate时,Item模型不在该类的范围内,或者是Nest.js库需要模型名称作为其自身模型的一部分。你应该尝试将item.schema导入到cabinet.schema中,看看是否还需要在populate中显式地声明Item

相关问题