非规范化架构?

时间:2016-08-08 11:14:14

标签: node.js mongodb mongoose relayjs graphql-js

Mongoose架构:

const postType = new GraphQLObjectType({
    name: 'Post',
    fields: () => ({
        id: globalIdField('Post'),
        title: { type: GraphQLString },
        content: { type: GraphQLString },

        comments: {

            // ?????

        }
    }),
    interfaces: [nodeInterface],
})

我不想将评论和回复标准化,因为:

  • 我总是需要一起发表评论(一次性阅读
  • 我绝不会使用评论来查询或排序任何内容
  • 使用评论创建,更新和删除帖子要轻松得多(文档锁定

如果我将其标准化,我将不得不:

  • 从数据库发帖子
  • 从数据库中获取评论
  • 获取每个评论
  • 的回复

这是MongoDB的最大优势之一:专门针对您的应用程序数据需求对数据进行分组,但GraphQL和Relay.js似乎不支持这一点?

问题:

有没有办法让嵌套在单个帖子对象中的评论(或者至少让嵌套在单个评论中的回复)才能在一次阅读中获得整个内容?

GraphQL架构:

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?', }] } ):

[Route("ValuesForFalse/{param=false}")]
[Route("ValuesForTrue/{param=true}")]

1 个答案:

答案 0 :(得分:1)

  

这是MongoDB的最大优势之一:专门针对您的应用程序数据需求对数据进行分组,但GraphQL和Relay.js似乎并不支持它?

GraphQL确实支持您尝试做的事情。在进入细节之前,我们需要记住GraphQL是关于公开数据,而不是关于我们如何存储数据。我们可以以任何我们喜欢的方式存储 - 标准化或不标准化。我们只需要告诉GraphQL如何获取我们在GraphQL模式中定义的数据。

  

有没有办法让嵌套在单个帖子对象中的评论(或者至少让嵌套在单个评论中的回复)才能在一次阅读中获得整个内容?

是的,这是可能的。您只需将注释定义为列表即可。但是,GraphQL不支持GraphQL对象类型中的任意类型的字段。因此,我们需要定义单独的GraphQL类型。在您的mongoose架构中,comments是一个包含count条评论和评论data的对象。 data属性是另一种对象的列表。因此,我们需要定义两个GraphQL对象 - CommentCommentList。代码如下所示:

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],
});
  

我不想将评论和回复标准化,因为:

     
      
  • 我总是需要一起发表评论(一次性阅读)
  •   
  • 我绝不会使用评论来查询或排序任何内容
  •   
  • 使用评论(文档锁定)
  • 创建,更新和删除帖子要容易得多   

以上述方式定义帖子和评论GraphQL对象类型可以:

  • 一起阅读所有帖子评论
  • 不使用评论进行查询,因为它甚至没有id字段。
  • 以您喜欢的方式使用首选数据库实现注释操作。 GraphQL与它无关。