【问题标题】:how to set many-to-many relation in graphql mutation?如何在graphql突变中设置多对多关系?
【发布时间】:2017-10-09 02:15:57
【问题描述】:

我可能遗漏了一些东西,但在 Apollo 文档上找不到任何关于在创建新条目时设置多对多关系的方式的信息。

当关系是一对多时,就像在多方对象中设置关系的一侧的ID一样简单。

但是让我们假设我正在使用书籍和作者,我将如何编写一个 graphql 查询来为一个(或多个?)作者创建一本书?

【问题讨论】:

    标签: graphql apollo react-apollo


    【解决方案1】:

    这可能发生在 GraphQL 服务器的 API 层(即模式)。对于多对多关系,您应该有一个“连接”类型来表示BookAuthor 多对多关系,然后向该连接类型添加一个条目。

    基本上,您将拥有一种称为Book 的类型,另一种称为Author,最后还有一种称为BookAuthor。你可以添加一些突变来管理这种关系。或许……

    • addToBookAuthorConnection
    • updateBookAuthorConnection
    • removeFromBookAuthorConnection

    这是使用符合 Relay 规范的 API 的常规设置。你可以read more about how to structure your API for many-to-many relationships here

    然后,您只需从 Apollo 调用 addToBookAuthorConnection 突变,即可添加到前端的多对多连接。

    希望这会有所帮助!

    【讨论】:

    • 感谢您的解释!!我应该提到我正在使用 graph.cool 作为后端。在这一点上没有挖掘他们的文档 - 愚弄我。文档在这个主题上似乎很短,但我联系了帮助台。我会在这里更新。
    • 我在 graphiQL 自动完成功能的帮助下找到了关系的名称。非常有用,因为这些名称在我的架构中没有出现...希望对其他人有所帮助。
    • 明白了! GraphiQL 是一个很好的工具,可以深入了解您的 API 并查看存在的内容。希望现在关系更加清晰。如果你有时间,你也应该看看Scaphold
    【解决方案2】:

    如果您使用具有一对多关系的 apollo 图形服务器,那么将 connector.js、resolvers.js 和 schema.js 文件作为给定格式

    schema.js

    const typeDefinitions = `
    
    
    
    type Author {
    
      authorId: Int
      firstName: String
      lastName: String
      posts: [Post]
    
    }
    
    type Post {
    
      postId: Int
      title: String 
      text: String
      views: Int
      author: Author
    
    }
    
    input postInput{
      title: String 
      text: String
      views: Int
    }
    
    
    type Query {
    
      author(firstName: String, lastName: String): [Author]
      posts(postId: Int, title: String, text: String, views: Int): [Post]
    
    }
    
    
    
    type Mutation {
    
    createAuthor(firstName: String, lastName: String, posts:[postInput]): Author
    
    updateAuthor(authorId: Int, firstName: String, lastName: String, posts:[postInput]): String
    
    }
    
    
    schema {
      query: Query
      mutation:Mutation
    }
    `;
    
    export default [typeDefinitions];
    

    解析器.js

    import { Author } from './connectors';
    import { Post } from './connectors';
    
    
    const resolvers = {
    
      Query: {
        author(_, args) {
          return Author.findAll({ where: args });
        },
        posts(_, args) {
          return Post.findAll({ where: args });
        }
      },
    
      Mutation: {
    
        createAuthor(_, args) {
          console.log(args)
          return Author.create(args, {
            include: [{
              model: Post,
            }]
          });
        },
    
        updateAuthor(_, args) {
    
          var updateProfile = { title: "name here" };
          console.log(args.authorId)
          var filter = {
            where: {
              authorId: args.authorId
            },
            include: [
              { model: Post }
            ]
          };
          Author.findOne(filter).then(function (product) {
            Author.update(args, { where: { authorId: args.authorId } }).then(function (result) {
              product.posts[0].updateAttributes(args.posts[0]).then(function (result) {
                //return result;
              })
            });
          })
          return "updated";
        },
    
      },
    
    
      Author: {
        posts(author) {
          return author.getPosts();
        },
      },
      Post: {
        author(post) {
          return post.getAuthor();
        },
      },
    };
    
    export default resolvers;
    

    connectors.js

    import rp from 'request-promise';
    var Sequelize = require('sequelize');
    var db = new Sequelize('test', 'postgres', 'postgres', {
      host: '192.168.1.168',
      dialect: 'postgres',
    
      pool: {
        max: 5,
        min: 0,
        idle: 10000
      }
    
    });
    
    
    const AuthorModel = db.define('author', {
      authorId: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, field: "author_id" },
      firstName: { type: Sequelize.STRING, field: "first_name" },
      lastName: { type: Sequelize.STRING, field: "last_name" },
    },{
            freezeTableName: false,
            timestamps: false,
            underscored: false,
            tableName: "author"
        });
    
    
    const PostModel = db.define('post', {
        postId: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, field: "post_id" },
      text: { type: Sequelize.STRING },
      title:  { type: Sequelize.STRING },
      views: { type: Sequelize.INTEGER },
    },{
            freezeTableName: false,
            timestamps: false,
            underscored: false,
            tableName: "post"
        });
    
    
    AuthorModel.hasMany(PostModel, {
        foreignKey: 'author_id'
    });
    PostModel.belongsTo(AuthorModel, {
        foreignKey: 'author_id'
    });
    
    const Author = db.models.author;
    const Post = db.models.post;
    
    export { Author, Post };
    

    【讨论】:

    • 明确定义字段和这样做有什么区别? AuthorModel.hasMany(PostModel, { through: 'AuthorPosts' });
    • 我认为这段代码适用于一对多(作者)而不是多对多。
    猜你喜欢
    • 2019-09-10
    • 2021-02-24
    • 2018-09-28
    • 2019-11-10
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 2015-12-20
    • 2018-06-25
    相关资源
    最近更新 更多