【问题标题】:Redux normalized state tree for posts and comments帖子和评论的 Redux 标准化状态树
【发布时间】:2016-11-22 01:46:46
【问题描述】:

Redux 建议使用规范化的应用程序状态树,但我不确定这是否是这种情况下的最佳实践。假设以下情况:

  1. 每个Circle has_many Posts
  2. 每个Post has_many Comments

在后端的数据库中,每个模型如下所示:

圈子:

{
  _id: '1'
  title: 'BoyBand'
}

帖子:

{
  _id: '1',
  circle_id: '1',
  body: "Some Post"
}

评论:

{
  _id: '1',
  post_id: '1',
  body: "Some Comment"
}

在前端的应用状态(所有reducer的最终结果)是这样的:

{
  circles: {
    byId: {
      1: {
        title: 'BoyBand'
      }
    },
    allIds: [1]
  },
  posts: {
    byId: {
      1: {
        circle_id: '1',
        body: 'Some Post'
      }
    },
    allIds: [1]
  },
  comments: {
    byId: {
      1: {
        post_id: '1',
        body: 'Some Comment'
      },
    allIds: [1]
  }
}

现在,当我转到CircleView 时,我从后端获取Circle,该后端返回与之关联的所有postscomments

export const fetchCircle = (title) => (dispatch, getState) => {
  dispatch({
    type: constants.REQUEST_CIRCLE,
    data: { title: title }
  })

  request
    .get(`${API_URL}/circles/${title}`)
    .end((err, res) => {
      if (err) {
        return
      }

      // When you fetch circle from the API, the API returns:
      // {
      //   circle: circleObj,
      //   posts: postsArr,
      //   comments: commentsArr
      // }
      // so it's easier for the reducers to consume the data

      dispatch({
        type: constants.RECEIVE_CIRCLE,
        data: (normalize(res.body.circle, schema.circle))
      })
      dispatch({
        type: 'RECEIVE_POSTS',
        data: (normalize(res.body.posts, schema.arrayOfPosts))
      })
      dispatch({
        type: 'RECEIVE_COMMENTS',
        data: (normalize(res.body.comments, schema.arrayOfComments))
      })
    })
}

到目前为止,我认为我所做的一切都是相当标准的。但是,当我想渲染每个 Post 组件时,我意识到与将状态树保持在以下格式时相比,使用它们的 cmets 填充帖子变得效率低下 (O(N^2))。

{
  circles: {
    byId: {
      1: {
        title: 'BoyBand'
      }
    },
    allIds: [1]
  },
  posts: {
    byId: {
      1: {
        circle_id: '1',
        body: 'Some Post'
        comments: [arrOfComments]
      }
    },
    allIds: [1]
  }
}

这违背了我的理解,在 redux 状态树中,最好保持一切正常化。

问。在这样的情况下,我实际上是否应该保持非规范化?我如何确定要做什么?

【问题讨论】:

  • 您是担心性能、重建树还是什么?
  • 你能添加造成性能瓶颈的代码吗?组件和容器代码可能吗?
  • 因为您的方法没有什么不好,您只需根据评论的 id 选择 cmets 正文,即使它是 O(n^2) 其中 n 是帖子的数量,它不应该是太多了。

标签: mongodb redux


【解决方案1】:

在我看来,cmets 列表是针对任何帖子的。用户不能将一条评论发布到多个帖子中。 cmets与post紧密耦合并没有错。更新/删除特定评论很容易(postId 和 commentId 都存在)。删除帖子是微不足道的。与圆圈相同。删除特定用户的所有 cmets 非常困难。而且我认为没有严格的规则,正确的方式等等......更多情况下取决于。 KiSS ;)

在考虑如何在客户端组织 cmets 时,我正在阅读这篇文章,它是关于类似情况下可能的数据库结构。 https://docs.mongodb.com/ecosystem/use-cases/storing-comments/

【讨论】:

    【解决方案2】:

    我会选择:是的,将其标准化,但在后端进行!

    为什么?

    • 删除更简单

    因为否则,每次您想要删除一个圈子或帖子时,您都必须追踪帖子和 cmets。

    • 处理数据更容易

    因为否则,您必须一遍又一遍地对数据进行相同的更改,以便您可以选择与特定圈子或帖子相关的数据集。

    • 您没有任何多对多关系

    您没有多个帖子链接到同一个评论,因此将数据标准化是有意义的。

    • 您不应受到 API 的限制

    如果这是第三方 API,则让您的后端获取 API 并规范那里的数据。你不应该受到 API 的限制,我不知道你访问什么样的数据,但是如果 API 不可用,你可以明确地为用户保存 DNS 查找并提供缓存的数据。如果您依赖 API 来启动,则会引入单点故障。


    关于您的性能问题,如果您在后端进行规范化,它们应该是微不足道的,您应该对其进行衡量,并将关键代码用于代码审查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 2023-03-16
      • 2017-09-22
      • 2022-01-10
      • 2012-09-14
      相关资源
      最近更新 更多