简体   繁体   中英

@nestjs/mongoose, virtual populate with 2 databases

I'm trying to populate userId field which exists in database 1 from user document which exists in database 2.

I've already defined connectionName parameter in MongooseModule.ForRootAsync() I can't find out where the problem is. Also it works if I request info from db1 and db2 individually.

Actually on console.log(commentPopulated) userId field is just the objectId without populated fields from User schema and also sometimes with certain @Prop() and .populate() parameters app throw me this error:

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

Using @nestjs/mongoose decorators how do I achieve this?

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
    }
}

I have tried randomly playing with parameters on @Prop() decorator with no success, I think there is the problem, also played with .populate() function parameters.

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');

this example this from mongoose docs Cross Database Populate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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