Graphql с внешним ключом sequelize join

Я сделал простую систему api платы с помощью graphql.

И я использую sequelize (версия 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!
}

[resolvers.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.info('[*] DB Sync Done'))

Article и Comment имеют соотношение 1: N.

Поэтому я установил hasMany на Article и установил belongsTo на Comment.

Также прокомментируйте как комментарий и включите его в объем статьи.

Но когда я запрашиваю запрос { article(id:1) { subject, comment } },

комментарий return 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
    }
  }
}

Я хочу отобразить все комментарии, относящиеся к конкретной статье.

Есть ли какое-то решение по этому поводу?

Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
2 645
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Пара замечаний, которые помогут вам встать на верный путь:

При определении отношения имейте в виду, что модель, метод которой вы вызываете, является той, к которой вы фактически добавляете свойство. Например, если вы вызовете Article.hasMany(Comment), это создаст свойство comments в модели Article и повлияет на модель Comment. Точно так же вызов Comment.belongsTo(Article) создаст свойство article в модели Comment и не повлияет на модель Article.

Обратите внимание, что даже если связь создана, если вы хотите включать связанных комментариев при запросе статьи (или наоборот), вы должны передать соответствующую опцию include. Это можно сделать прямо в вызове запроса, т.е.

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

или может быть частью области действия, например области действия по умолчанию. Области могут быть установлены как часть определения модели или добавлены постфактум путем вызова addScope. Например, вы можете:

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

Примечание: override здесь необходим, потому что область по умолчанию уже существует. Чтобы запросить связанные модели, ваш вызов запроса или область, которую вы используете, должны включать соответствующий массив include. Ассоциации также имеют понятие «масштаб», но оно отличается от объема модели. См. Документацию здесь для обсуждения различий.

Наконец, при передаче опции 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. Но после проверки базы данных дополнительного столбца нет. Итак, я думаю, дополнительный столбец не относится к реальной базе данных, верно?

Hide 06.07.2018 02:28

И должен ли я установить и Article.hasMany(Comment), и Comment.belongsTo(Article) в соотношении 1: N? Или просто установить между ними одну связь?

Hide 06.07.2018 02:34

Если я правильно помню, hasMany или belongsTo должны создать соответствующий столбец (в данном случае в таблице статей). Независимо от того, используете ли вы один или другой, или оба, опять же, зависит от того, нужно ли вам, чтобы ваш экземпляр модели Article имел свойство comments или вам нужно, чтобы ваш экземпляр модели комментариев имел свойство article (или оба).

Daniel Rearden 06.07.2018 03:31

FWIW, при использовании sequelize.sync() вам может потребоваться установить для параметра force значение true, чтобы увидеть, как ваши изменения применяются к вашей базе данных (docs.sequelizejs.com/class/lib/…)

Daniel Rearden 06.07.2018 03:34

Спасибо! Я попробую.

Hide 10.07.2018 06:59

Есть проблемы с вашей схемой graphql и схемой sequelize ...

Давайте посмотрим на вашу схему graphql

type Article {
    ...
    comment: String
}

Вы написали, что статья и комментарий имеют отношение 1: M но здесь поле комментария имеет тип строки, а не массив строки

правильное определение типа для статьи должно быть (imo):

type Article {
    ...
    comments: [Comment] 
}

теперь, если вы внесете изменения в схему продолжения, @ Daniel-Rearden написал в своем ответе, что ваша модель Article должна иметь свойство comments, поэтому оно будет возвращено по умолчанию из default resolver типа Article.

Comment[] - это ошибка выдачи Syntax Error: Expected Name, found [. Может быть, [Comment] правильный путь.
Hide 06.07.2018 02:18

Другие вопросы по теме