【问题标题】:graphql with sequelize join foreign key带有续集的graphql加入外键
【发布时间】:2018-12-12 09:27:11
【问题描述】:

我用graphql做了一个简单的board api系统。

我使用 sequelize(version 4) 连接数据库。

[schema.graphql]

type Article {
    article_no: Int!
    subject: String!
    content: String!
    createdAt: String!
    updatedAt: String!
    comment: String
}

type Comment {
    article_no: Int!
    content: String!,
    createdAt: String!
}

type Query {
    articles: [Article]!
    article(article_no: Int!): Article
    comments: [Comment]!
    comment(article_no: Int!): Comment
}

type Mutation {
    createArticle(subject: String!, content: String!, password: String!): Boolean!
    createComment(article_no: Int!, content: String!, password: String!): Boolean!
}

[解析器.js]

import { Article, Comment } from './db';

const resolvers = {
    Query: {
        articles: async () => {
            return Article.all();
        },
        article: async(_, args) => {
            return Article.find({
                where: args.article_no,
            });
        },
        comments: async () => {
            return Comment.all();
        },
        comment: async(_, args) => {
            return Comment.find({
                where: args.article_no
            });
        }
    },
    Mutation: {
        createArticle: async (_, args) => {
            try {
                const article = await Article.create({
                    subject: args.subject,
                    content: args.content,
                    password: args.password
                });
                return true;
            } catch(e) {
                return false;
            }
        },
        createComment: async(_, args) => {
            try {
                const comment = await Comment.create({
                    article_no: args.article_no,
                    content: args.content,
                    password: args.password
                })
                return comment;
            } catch(e) {
                return false;
            }
        }
    }
}

export default resolvers;

[db.js]

const Sequelize = require('sequelize');
import config from '../config/config';

const db = new Sequelize(config.DB, config.USER, config.PASS, {
    host: 'localhost',
    dialect: 'mysql'
})

export const Article = db.define('article', {
    article_no: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    subject: {
        type: Sequelize.STRING(30),
        allowNull: false
    },
    content: {
        type: Sequelize.STRING(100),
        allowNull: false
    },
    password: {
        type: Sequelize.STRING(20),
        allowNull: false
    },
    comment: Sequelize.STRING
}, {
    freezeTableName: true,
    timestamps: true,
    underscored: true
})

export const Comment = db.define('comment', {
    content: {
        type: Sequelize.STRING(150),
        allowNull: false
    },
    password: {
        type: Sequelize.STRING(20),
        allowNull: false
    },
}, {
    freezeTableName: true,
    timestamps: true,
    underscored: true
})

Article.hasMany(Comment, {
    foreignKey: 'article_no',
    scope: {
        comment: 'comment'
    }
})
Comment.belongsTo(Article, {
    foreignKey: 'article_no',
    targetKey: 'article_no',
    allowNull: false,
    as: 'comment'
});
db.sync()
.then(console.log('[*] DB Sync Done'))

ArticleComment 是 1:N 关系。

所以我将hasMany 设置为Article 并将belongsTo 设置为Comment

也将评论作为评论并将其包含在文章的范围内。

但是当我请求查询{ article(id:1) { subject, comment } }时,

评论返回null。

我参考了文档http://docs.sequelizejs.com/manual/tutorial/associations.html#foreign-keys 并关注。

但它不起作用。

我的预期结果在这里:

{
  "data": {
    "article": {
      "subject": "test",
      "comment": {
           "article_no":1,
           "content: "first comment",
           "created_at": "2018010101001",
           # every comment related article is here
      }
    }
  }
}

当前结果在这里:

{
  "data": {
    "article": {
      "subject": "test",
      "comment": null
    }
  }
}

我想显示与特定文章相关的所有 cmets。

有什么解决办法吗?

谢谢。

【问题讨论】:

    标签: sequelize.js graphql


    【解决方案1】:

    几条笔记让你走上正轨:

    在定义关系时,请记住,您正在调用其方法的模型是您有效添加属性的模型。例如,如果您调用Article.hasMany(Comment),这将在Article 模型上创建comments 属性,并将影响Comment 模型。同样,调用Comment.belongsTo(Article) 将在Comment 模型上创建article 属性,并且不会影响Article 模型。

    请注意,即使创建了关系,如果您想在查询文章时包含关联的 cmets(反之亦然),您必须传入适当的 include 选项。这可以直接在查询调用中完成,即

    Article.findAll({ include: [Comment] })
    

    或者可以是范围的一部分,例如默认范围。范围可以设置为模型定义的一部分,或者通过调用addScope 在事后添加。例如,您可以这样做:

    Article.addScope('defaultScope', {
      include: [Comment],
    }, { override: true })
    

    注意:这里的override 是必需的,因为默认范围已经存在。要查询关联模型,您的查询调用或您正在使用的范围必须包含适当的 include 数组。关联也有“范围”的概念,但它与模型的范围不同。有关差异的讨论,请参阅文档 here

    最后,在将 where 选项传递给您的 find 调用时,您应该确保它包含您要查询的属性名称,即

    Article.find({ where: { article_no: args.article_no } })
    
    // or possibly even
    Article.find({ where: args })
    

    【讨论】:

    • 你说if you call Article.hasMany(Comment), this will create a comments property on the Article model and will affect the Comment model。但是在我检查数据库之后,没有额外的列。所以我认为,附加列不适用于真实数据库,对吧?
    • 而且,我应该将Article.hasMany(Comment)Comment.belongsTo(Article) 都设置为1:N 关系吗?或者只是在这两者之间设置一种关系?
    • 如果我没记错的话,hasManybelongsTo 应该创建适当的列(在本例中是在文章表中)。使用其中一个或另一个,或者两者都使用取决于您是否需要 Article 模型实例具有 comments 属性,或者您的 Comments 模型实例是否需要具有 article 属性(或两者兼而有之)。跨度>
    • FWIW,使用 sequelize.sync() 时,您可能需要将 force 选项设置为 true 才能看到您的更改应用于您的数据库 (docs.sequelizejs.com/class/lib/…)
    • 谢谢!我会试试的。
    【解决方案2】:

    您的 graphql 架构和您的 sequelize 架构存在问题...

    让我们看看你的 graphql 架构

    输入文章{ ... 评论:字符串 }

    您写道,文章和评论具有 1:M 关系 但这里的注释字段是字符串类型,甚至不是字符串数组

    Article 的正确类型定义应该是 (imo):

    输入文章{ ... cmets:[评论] }

    现在,如果您对 @Daniel-Rearden 的续集架构进行调整 在他的回答中写道,您的 Article 模型应该具有 comments 属性,因此默认情况下它将从 Article 类型的 default resolver 返回

    【讨论】:

    • Comment[] 是抛出错误Syntax Error: Expected Name, found [。也许[Comment] 是正确的方式。
    猜你喜欢
    • 2021-06-24
    • 2013-09-27
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    相关资源
    最近更新 更多