Я сделал простую систему 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
}
}
}
Я хочу отобразить все комментарии, относящиеся к конкретной статье.
Есть ли какое-то решение по этому поводу?
Спасибо.





Пара замечаний, которые помогут вам встать на верный путь:
При определении отношения имейте в виду, что модель, метод которой вы вызываете, является той, к которой вы фактически добавляете свойство. Например, если вы вызовете 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 })
И должен ли я установить и Article.hasMany(Comment), и Comment.belongsTo(Article) в соотношении 1: N? Или просто установить между ними одну связь?
Если я правильно помню, hasMany или belongsTo должны создать соответствующий столбец (в данном случае в таблице статей). Независимо от того, используете ли вы один или другой, или оба, опять же, зависит от того, нужно ли вам, чтобы ваш экземпляр модели Article имел свойство comments или вам нужно, чтобы ваш экземпляр модели комментариев имел свойство article (или оба).
FWIW, при использовании sequelize.sync() вам может потребоваться установить для параметра force значение true, чтобы увидеть, как ваши изменения применяются к вашей базе данных (docs.sequelizejs.com/class/lib/…)
Спасибо! Я попробую.
Есть проблемы с вашей схемой 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] правильный путь.
Вы сказали
if you call Article.hasMany(Comment), this will create a comments property on the Article model and will affect the Comment model. Но после проверки базы данных дополнительного столбца нет. Итак, я думаю, дополнительный столбец не относится к реальной базе данных, верно?