繁体   English   中英

@nestjs/mongoose,虚拟填充 2 个数据库

[英]@nestjs/mongoose, virtual populate with 2 databases

我正在尝试从数据库 2 中存在的用户文档填充数据库 1 中存在的 userId 字段。

我已经在MongooseModule.ForRootAsync()中定义了connectionName参数,我找不到问题出在哪里。 如果我分别从db1db2请求信息,它也可以工作。

实际上在console.log(commentPopulated)上, userId字段只是 objectId,没有来自 User 模式的填充字段,有时还带有某些@Prop().populate()参数应用程序抛出这个错误:

MissingSchemaError: Schema hasn't been registered for model "User".

使用@nestjs/mongoose装饰器我该如何实现?

app.module.ts

MongooseModule.forRootAsync({
  connectionName: 'db1',
  useFactory: () => ({
    uri: process.env.DB1,
    connectionFactory: (connection: { plugin: (arg0: unknown) => void }) => {
      connection.plugin(_)
      connection.plugin(autoPopulate)
      return connection
    },
  }),
}),
MongooseModule.forRootAsync({
  connectionName: 'db2',
  useFactory: () => ({
    uri: process.env.DB2,
    connectionFactory: (connection: { plugin: (arg0: unknown) => void }) => {
      connection.plugin(_)
      connection.plugin(autoPopulate)
      return connection
    },
  }),
}),

comment.module.ts

const commentModule: DynamicModule = MongooseModule.forFeatureAsync([
    {
        name: Comment.name,
        useFactory: () => {
            return CommentSchema
        }
    }
], 'db1')

@Module({
    imports: [commentModule],
    providers: [CommentService, CommentResolver]
})
export class CommentModule { }

comment.schema.ts

@Schema({ toJSON: { virtuals: true, getters: true }, toObject: { virtuals: true, getters: true } })
@ObjectType()
export class Comment extends Document {
    @Prop()
    @Field(() => String)
    readonly _id: MongooseSchema.Types.ObjectId

    @Prop({ required: true })
    @Field(() => String)
    text: string

    //TODO: Reference User document from DB2, Comment document exists in DB1
    @Prop({ type: MongooseSchema.Types.ObjectId, virtualpath: User.name, virtuals: true })
    @Field(() => User, { nullable: true })
    userId: MongooseSchema.Types.ObjectId

    @Prop({ type: String, enum: UserType, required: true, default: UserType.Regular })
    @Field(() => UserType, { defaultValue: UserType.Regular })
    userType: UserType

    @Prop({ default: Date.now })
    @Field(() => Date)
    created: Date
}

export const CommentSchema = SchemaFactory.createForClass(Comment)

user.module.ts

const userModule: DynamicModule = MongooseModule.forFeatureAsync([
  {
    name: User.name,
    useFactory: () => {
      return UserSchema
    },
  },
], 'db2')

@Module({
  imports: [userModule],
  providers: [UserService, UserResolver]
})
export class UserModule { }

user.schema.ts

@Schema()
@ObjectType()
export class User extends Document {
    @Prop()
    @Field(() => String)
    readonly _id: MongooseSchema.Types.ObjectId

    @Prop({ required: true })
    @Field(() => String)
    firstName: string

    @Prop({ required: true })
    @Field(() => String)
    lastName: string

    @Prop({ required: true })
    @Field(() => String)
    email: string
}

export const UserSchema = SchemaFactory.createForClass(User)

comment.service.ts

@Injectable()
export class CommentService {
    constructor(@InjectModel(Comment.name, 'db1') private readonly model: Model<Comment>) { }
    async getComments() {
        const commentPopulated = await this.model.findById('63b8608c7d4f880cba028bfe').populate('userId')
        console.log(commentPopulated)
        return commentPopulated
    }
}

我曾尝试在@Prop()装饰器上随机播放参数但没有成功,我认为存在问题,还播放了.populate() function 参数。

const db1 = mongoose.createConnection('mongodb://127.0.0.1:27000/db1');
const db2 = mongoose.createConnection('mongodb://127.0.0.1:27001/db2');

const userSchema = new Schema({...});
const User= db2.model('User', userSchema);

const commentSchema = new Schema({
...
user: {
type: ObjectId,
ref: User // `ref` is a **Model class**, not a string
}
});
const Comment = db1.model('Comment', commentSchema);

const comments = await Comment.
find().
populate('user');

这个例子来自mongoose docs Cross Database Populate

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM