代码之家  ›  专栏  ›  技术社区  ›  Romik romikromik

如何与裁判实现猫鼬中的一对多关系

  •  0
  • Romik romikromik  · 技术社区  · 3 年前

    我有两个模式。 PostSchema:

    export type PostDocument = Post & Document;
    
    @Schema({ collection: 'posts' })
    export class Post {
      @Prop()
      description: string;
      @Prop()
      title: string;
      // incorrect variant below
      @Prop({
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
      })
      _id: ObjectId;
    }
    const PostSchema = SchemaFactory.createForClass(Post);
    export { PostSchema as PostSchema };
    

    和UserSchema:

    export type UserDocument = User & Document;
    
    @Schema({
      collection: 'users',
    })
    export class User {
      @Prop()
      name: string;
      @Prop({
        type: [
          { type: mongoose.Schema.Types.ObjectId, ref: 'Post', autopopulate: true },
        ],
      })
      posts: Post[];
    }
    const UserSchema = SchemaFactory.createForClass(User);
    export { UserSchema as UserSchema };
    

    但我仍然不明白如何将第一张表与第二张表联系起来。在一张桌子上做所有事情要容易得多,但我对裁判的这种方法很感兴趣。

    0 回复  |  直到 3 年前
        1
  •  1
  •   Fabian Strathaus    3 年前

    首先,您永远不应该命名Mongoose属性 _id 。这是猫鼬内部用于标识单个文档的字段名。如果是你的话,我建议命名 userId 或 authorId (根据代码上下文假设)。

    尽管如此,在猫鼬中定义一对多关系基本上有两种选择:

    1. 在Post架构中定义用户的ObjectId。
    2. 在用户架构中定义Posts的ObjectId数组。

    基本上你两者都做了,这是可能的,但并不是最好的方法。这里的问题是,要使这两个独立的关系保持同步并不容易(请记住:您不是在使用关系数据库,必须自己删除引用)。

    建议的方法:

    在您的情况下,我建议您在Post模式中只定义用户的ObjectId(方法1),并在用户模式中创建一个名为“posts”的虚拟属性(如下图所示: https://mongoosejs.com/docs/tutorials/virtuals.html#populate ). 这样,就可以很容易地从两个方向填充数据,而不必跟踪数据同步,因为关系只在后模式中定义。您唯一应该解决的问题是,如果用户被删除,请将此Post属性设置为null。在这种情况下,您应该定义一个钩子。