Database design 图形模式设计:用户->;后->;评论
我刚开始使用neo4j,我对如何为用户->帖子->评论模式建模有些疑问……实际上我做了如下操作: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:
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
属性的查询更复杂,但它具有拥有依赖于图形数据库优势的清晰数据模型的所有优点
存储冗余数据感觉像是一种过早的优化——在您发现需要它来摆脱困境之前,我建议您的原始模型看起来非常适合图形。如果这还不足以给您信心,那么就进行实验,尝试这两种方法,看看查询的外观以及模型在您的用例中使用的感觉如何。请记住,您可以随时根据关系或存储额外属性重构图形,并在需求发生变化时再次重构图形