Database design 图形模式设计:用户->;后->;评论

Database design 图形模式设计:用户->;后->;评论,database-design,graph,neo4j,schema,Database Design,Graph,Neo4j,Schema,我刚开始使用neo4j,我对如何为用户->帖子->评论模式建模有些疑问……实际上我做了如下操作: type User { uuid: ID! username: String posts: [Post] @relation(name: "HAS_POSTS", direction: "OUT") comments: [Comment] @relation(name: "POST_COMMENTS", direction: "OUT") } type Post { uuid:

我刚开始使用neo4j,我对如何为用户->帖子->评论模式建模有些疑问……实际上我做了如下操作:

type User {
  uuid: ID!
  username: String
  posts: [Post] @relation(name: "HAS_POSTS", direction: "OUT")
  comments: [Comment] @relation(name: "POST_COMMENTS", direction: "OUT")
}

type Post {
  uuid: ID!
  text: String
  owner: User @relation(name: "HAS_POSTS", direction: "IN")
  comments: [Comment] @relation(name: "HAS_COMMENTS", direction: "OUT")
}

type Comment {
  uuid: ID!
  text: String
  owner: User @relation(name: "POST_COMMENTS", direction: "IN")
}
MATCH (p:Post) WHERE p.uuid = post.uuid AND p.owner = $cypherParams.user.uuid
      SET p += post
      RETURN p
保存引用对象的uuid,例如,每个帖子都有owner uuid作为属性,并且它也有关系(注释也是如此),但我不是100%认为这是正确的。阅读本文:

我理解为什么使用关系比属性更好,但如果我想编辑帖子,并确保只有帖子的所有者有权这样做,我想通过帖子的uuid和用户的uuid搜索帖子,然后在特定节点上设置数据……类似于这样:

type User {
  uuid: ID!
  username: String
  posts: [Post] @relation(name: "HAS_POSTS", direction: "OUT")
  comments: [Comment] @relation(name: "POST_COMMENTS", direction: "OUT")
}

type Post {
  uuid: ID!
  text: String
  owner: User @relation(name: "HAS_POSTS", direction: "IN")
  comments: [Comment] @relation(name: "HAS_COMMENTS", direction: "OUT")
}

type Comment {
  uuid: ID!
  text: String
  owner: User @relation(name: "POST_COMMENTS", direction: "IN")
}
MATCH (p:Post) WHERE p.uuid = post.uuid AND p.owner = $cypherParams.user.uuid
      SET p += post
      RETURN p
这个式样好吗?或者,保存所有者属性是无用的,可能会破坏数据的一致性


非常感谢

我认为在任何数据库(包括图表)中进行数据建模时,都没有很多明确的答案。我们所能做的是,如果要使用关系,那么可以查看特定的“编辑帖子”查询可能会发生的情况,以便查看比较

首先,让我们为我们的测试伪造
cypherParams
变量:

:param cypherParams => {
  user: {
    uuid: 123
  },
  post: {
    text: 'Made the post better',
    uuid: 2
  }
}
现在,让我们用Post和用户节点对问题的简化版本进行建模:

MERGE (u1: User { uuid: 123, name: 'Pablissimo' })
MERGE (u2: User { uuid: 234, name: 'Francesco' })
MERGE (p1: Post { uuid: 1, text: 'This post is great' })
MERGE (p2: Post { uuid: 2, text: 'This post not so great' })
MERGE (p3: Post { uuid: 3, text: 'This post is pretty good' })
MERGE (u1)-[:HAS_POST]->(p1)
MERGE (u1)-[:HAS_POST]->(p2)
MERGE (u2)-[:HAS_POST]->(p3)
RETURN p1, p2, p3, u1, u2

考虑到这一点,如果我是试图更新Post2的用户123,那么该查询会是什么样子

MATCH (u: User { uuid: $cypherParams.user.uuid })-[:HAS_POST]->(p: Post { uuid: $cypherParams.post.uuid })
SET p += $cypherParams.post
RETURN p

它实际上并不比Post节点具有
owner
属性的查询更复杂,但它具有拥有依赖于图形数据库优势的清晰数据模型的所有优点

存储冗余数据感觉像是一种过早的优化——在您发现需要它来摆脱困境之前,我建议您的原始模型看起来非常适合图形。如果这还不足以给您信心,那么就进行实验,尝试这两种方法,看看查询的外观以及模型在您的用例中使用的感觉如何。请记住,您可以随时根据关系或存储额外属性重构图形,并在需求发生变化时再次重构图形