非规范化架构?
Denormalized schema?
猫鼬模式:
const postSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
comments: {
count: { type: Number },
data: [{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
content: { type: String },
created: { type: Date },
replies: [{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
content: { type: String },
created: { type: Date },
}]
}]
}
})
我不想规范化评论和回复,因为:
- 我总是需要 post 评论(一次阅读)
- 我永远不会使用评论来查询或排序任何东西
- 创建、更新和删除 post 带注释(文档锁定)
如果我将它归一化,我将不得不:
- 从数据库中获取post
- 从数据库获取评论
- 获得对每个条评论的回复
这是 MongoDB 的最大优势之一:专门对数据进行分组以满足您的应用程序数据需求,但 GraphQL 和 Relay.js 似乎不支持?
问题:
有没有办法让评论嵌套在单个 post 对象中(或者至少让回复嵌套在单个评论中)以便在一次读取中获得全部内容?
GraphQL 架构:
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
comments: {
// ?????
}
}),
interfaces: [nodeInterface],
})
更新:
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
commentCount: { type: GraphQLInt },
comments: { type: new GraphQLList(commentType) }
}),
interfaces: [nodeInterface]
})
const commentType = new GraphQLObjectType({
name: 'Comment',
fields: () => ({
content: { type: GraphQLString },
created: { type: GraphQLString },
author: {
type: userType,
resolve: async (comment) => {
return await getUserById(comment.author)
}
},
replies: {
type: new GraphQLList(commentType),
resolve: (comment) => {
// Log is below
console.log(comment)
// Error only occurs if I return it!
return comment.replies
}
}
})
})
日志 (comment
):
{
author: 'user-1',
created: '05:35'
content: 'Wow, this is an awesome comment!',
replies:
[{
author: 'user-2',
created: '11:01',
content: 'Not really..',
},
{
author: 'user-1',
created: '11:03',
content: 'Why are you so salty?',
}]
}
This is one of the biggest strengths of MongoDB: to group your data specifically to suit your application data needs but GraphQL and Relay.js doesn't seem to support that?
GraphQL 确实支持您尝试做的事情。在进入细节之前,我们需要记住 GraphQL 是关于公开数据,而不是关于我们如何存储数据。我们可以以任何我们喜欢的方式存储——规范化或非规范化。我们只需要告诉 GraphQL 如何获取我们在 GraphQL 模式中定义的数据。
Is there a way to get comments nested inside of a single post object (or at least get replies nested inside of a single comment) in order to get the whole thing in a single read?
是的,这是可能的。您只需将评论定义为列表。但是,GraphQL 不支持 GraphQL 对象类型中的任意类型的字段。因此,我们需要定义单独的 GraphQL 类型。在您的猫鼬模式中,comments
是一个具有 count
条评论和 data
条评论的对象。 data
属性 是另一类对象的列表。因此,我们需要定义两个 GraphQL 对象 - Comment
和 CommentList
。代码如下所示:
const commentType = new GraphQLObjectType({
name: 'Comment',
fields: () => ({
author: { type: GraphQLString },
content: { type: GraphQLString },
created: { type: GraphQLString },
replies: { type: new GraphQLList(commentType) },
}),
});
const commentListType = new GraphQLObjectType({
name: 'CommentList',
fields: () => ({
count: {
type: GraphQLInt,
resolve: (comments) => comments.length,
},
data: {
type: new GraphQLList(commentType),
resolve: (comments) => comments,
},
}),
});
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
comments: {
type: commentListType,
resolve: (post) => post.comments,
}
}),
interfaces: [nodeInterface],
});
I don't want to normalize comments and replies because:
- I will always need post comments together (read in a single go)
- I will never use comments to query or sort anything
- It's so much easier to create, update and delete post with comments (document locking)
以上述方式定义 post 和注释 GraphQL 对象类型让您:
- 一起阅读所有 post 条评论
- 不要使用注释查询,因为它甚至没有
id
字段。
- 使用您喜欢的数据库以您喜欢的任何方式实施评论操作。 GraphQL 与它无关。
猫鼬模式:
const postSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
comments: {
count: { type: Number },
data: [{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
content: { type: String },
created: { type: Date },
replies: [{
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
content: { type: String },
created: { type: Date },
}]
}]
}
})
我不想规范化评论和回复,因为:
- 我总是需要 post 评论(一次阅读)
- 我永远不会使用评论来查询或排序任何东西
- 创建、更新和删除 post 带注释(文档锁定)
如果我将它归一化,我将不得不:
- 从数据库中获取post
- 从数据库获取评论
- 获得对每个条评论的回复
这是 MongoDB 的最大优势之一:专门对数据进行分组以满足您的应用程序数据需求,但 GraphQL 和 Relay.js 似乎不支持?
问题:
有没有办法让评论嵌套在单个 post 对象中(或者至少让回复嵌套在单个评论中)以便在一次读取中获得全部内容?
GraphQL 架构:
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
comments: {
// ?????
}
}),
interfaces: [nodeInterface],
})
更新:
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
commentCount: { type: GraphQLInt },
comments: { type: new GraphQLList(commentType) }
}),
interfaces: [nodeInterface]
})
const commentType = new GraphQLObjectType({
name: 'Comment',
fields: () => ({
content: { type: GraphQLString },
created: { type: GraphQLString },
author: {
type: userType,
resolve: async (comment) => {
return await getUserById(comment.author)
}
},
replies: {
type: new GraphQLList(commentType),
resolve: (comment) => {
// Log is below
console.log(comment)
// Error only occurs if I return it!
return comment.replies
}
}
})
})
日志 (comment
):
{
author: 'user-1',
created: '05:35'
content: 'Wow, this is an awesome comment!',
replies:
[{
author: 'user-2',
created: '11:01',
content: 'Not really..',
},
{
author: 'user-1',
created: '11:03',
content: 'Why are you so salty?',
}]
}
This is one of the biggest strengths of MongoDB: to group your data specifically to suit your application data needs but GraphQL and Relay.js doesn't seem to support that?
GraphQL 确实支持您尝试做的事情。在进入细节之前,我们需要记住 GraphQL 是关于公开数据,而不是关于我们如何存储数据。我们可以以任何我们喜欢的方式存储——规范化或非规范化。我们只需要告诉 GraphQL 如何获取我们在 GraphQL 模式中定义的数据。
Is there a way to get comments nested inside of a single post object (or at least get replies nested inside of a single comment) in order to get the whole thing in a single read?
是的,这是可能的。您只需将评论定义为列表。但是,GraphQL 不支持 GraphQL 对象类型中的任意类型的字段。因此,我们需要定义单独的 GraphQL 类型。在您的猫鼬模式中,comments
是一个具有 count
条评论和 data
条评论的对象。 data
属性 是另一类对象的列表。因此,我们需要定义两个 GraphQL 对象 - Comment
和 CommentList
。代码如下所示:
const commentType = new GraphQLObjectType({
name: 'Comment',
fields: () => ({
author: { type: GraphQLString },
content: { type: GraphQLString },
created: { type: GraphQLString },
replies: { type: new GraphQLList(commentType) },
}),
});
const commentListType = new GraphQLObjectType({
name: 'CommentList',
fields: () => ({
count: {
type: GraphQLInt,
resolve: (comments) => comments.length,
},
data: {
type: new GraphQLList(commentType),
resolve: (comments) => comments,
},
}),
});
const postType = new GraphQLObjectType({
name: 'Post',
fields: () => ({
id: globalIdField('Post'),
title: { type: GraphQLString },
content: { type: GraphQLString },
comments: {
type: commentListType,
resolve: (post) => post.comments,
}
}),
interfaces: [nodeInterface],
});
I don't want to normalize comments and replies because:
- I will always need post comments together (read in a single go)
- I will never use comments to query or sort anything
- It's so much easier to create, update and delete post with comments (document locking)
以上述方式定义 post 和注释 GraphQL 对象类型让您:
- 一起阅读所有 post 条评论
- 不要使用注释查询,因为它甚至没有
id
字段。 - 使用您喜欢的数据库以您喜欢的任何方式实施评论操作。 GraphQL 与它无关。