graphql和sequelize:用户和追随者/追随者

6ojccjat  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(476)

我正试图建立我的 User graphql模型 followers 以及 following 要查询的属性。不过,我在sequelize中建立关系有困难。我在试着用 Follower 作为联接表建模并设置 BelongsToMany 但没能让它工作。有人能建议我做什么或指出我做错了什么吗?
我通过手动查询找到了一个临时解决方案,您可以在我的 User.model.ts ,但我相信有一个更好的方法来使用适当的配置。
我在graphql和sequelize、typegraphql和sequelize typescript以及postgresql周围使用typescript Package 器。
用户.model.ts

// VENDOR
import { ObjectType, Field, ID } from 'type-graphql';
import { Model, Table, Column, PrimaryKey, Unique, IsUUID, HasMany, DefaultScope, AllowNull, DataType, BelongsToMany } from 'sequelize-typescript';
// APP
import Post from '../post/post.types';
import Follower from '../follower/follower.types';

/**User model for GraphQL & Database */
@Table({ timestamps: false, tableName: 'users' }) // tell sequelize to treat class as table model
@DefaultScope(() => ({ include: [{ model: Post.scope(), as: 'posts' }] })) // tell sequelize to include posts in its default queries
@ObjectType() // tell GraphQL to treat class as GraphQL model
export default class User extends Model<User>{

    @PrimaryKey
    @Unique
    @AllowNull(false)
    @IsUUID(4)
    @Column(DataType.UUID)
    @Field(() => ID)
    id: string;

    @Unique
    @AllowNull(false)
    @Column
    @Field()
    ci_username: string;

    @AllowNull(false)
    @Column
    @Field()
    username: string;

    @AllowNull(false)
    @Column
    @Field()
    first_name: string;

    @Column
    @Field()
    last_name: string;

    @Column
    @Field({ nullable: true })
    profile_picture?: string;

    // @BelongsToMany(() => User, { otherKey: 'user_id', as: 'followers', through: () => Follower })
    // @Field(() => [User])
    // followers: User[];

    // MY TEMPORARY SOLUTION USING MANUAL QUERYING
    @Field(() => [User])
    get followers(): Promise<User[]> {
        return Follower.findAll({ where: { user_id: this.id } })
            .then(records => records.map(record => record.follower_id))
            .then((follower_ids: string[]) => {
                return User.findAll({ where: { id: follower_ids }});
            })
    }

    // DOES NOT WORK, BUT I BELIEVE COULD POTENTIALLY LEAD TO BETTER SOLUTION
    @BelongsToMany(() => User, { otherKey: 'follower_id', as: 'following', through: () => Follower })
    @Field(() => [User])
    following: User[];

    @HasMany(() => Post)
    @Field(() => [Post])
    posts: Post[];
}

从动件.model.ts

// VENDOR
import { Model, Table, Column, PrimaryKey, Unique, IsUUID, AllowNull, DataType, Index, ForeignKey, AutoIncrement } from 'sequelize-typescript';

// APP
import User from '../user/user.types';

/**Follower model for Database */
@Table({ timestamps: false, tableName: 'followers' }) // tell sequelize to treat class as table model
export default class Follower extends Model<Follower>{

    @PrimaryKey
    @AutoIncrement
    @Unique
    @AllowNull(false)
    @Column
    id: number;

    @AllowNull(false)
    @IsUUID(4)
    @Index
    @ForeignKey(() => User)
    @Column(DataType.UUID)
    user_id: string;

    @AllowNull(false)
    @IsUUID(4)
    @Index
    @ForeignKey(() => User)
    @Column(DataType.UUID)
    follower_id: string;
}

graphql查询

{
  users: allUsers {
    id
    username
    first_name
    last_name
    following {
      username
      id
    }
  }
}

graphql响应/错误

{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field User.following.",
      "locations": [
        {
          "line": 7,
          "column": 5
        }
      ],
      "path": [
        "users",
        0,
        "following"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field User.following.",
            "    at completeValue (/Users/jsainz237/Projects/trueview/trueview-api/node_modules/graphql/execution/execute.js:560:13)",
            "    at /Users/jsainz237/Projects/trueview/trueview-api/node_modules/graphql/execution/execute.js:492:16"
          ]
        }
      }
    }
  ],
  "data": null
}

感谢您的帮助。

sycxhyv7

sycxhyv71#

你需要写一个 @FieldResolver 手动解决关系并返回正确的数据。
另一种解决方案是依赖orm功能和延迟关系—当返回的基实体包含一个promise作为字段时,那么当 .then() 调用时,它会自动获取数据库的关系。

相关问题