【问题标题】:Graph or relational database is better for this tree structure?图形或关系数据库更适合这种树结构?
【发布时间】:2019-04-01 15:58:16
【问题描述】:

我是图形数据库的新手,需要针对这种情况的建议。我有人喜欢这些类别(只有树上的叶子),其他节点(父母)没有得到“喜欢”。然后我计算特定用户与其他用户的所有连接的分数。这是一个图形示例:

我尝试使用 neo4j,我没有问题(非常小的数据集),但我担心很多用户的性能。我用以下查询进行了测试:

MATCH (n:Person)-[:LIKES*]->()-[r:SUB*0..4]-()<-[:LIKES*]-(m:Person)
WHERE n.name='Gabriel' and n<>m
WITH n.name as user, m.name as connection, 1.0/(length(r)+1)*count(r) as score
RETURN user, connection, sum(score)

我也考虑过在关系数据库中做这件事,为类别喜欢(cat1,cat2,cat3)保存 3 个字段,然后进行 3 个自连接,在不同的类别级别中寻找匹配项。类似的东西(从用户 1 开始并尝试与其他人匹配):

select l2.user_id, sum(
case 
    when (l1.cat2 = l2.cat2 and l1.cat3 = l2.cat3) then 1
    when (l1.cat2 = l2.cat2) then 0.25 
    else 0.05 
end)
from likes l1
inner join likes l2 on l1.cat1 = l2.cat1 and l2.user_id <> 1
where l1.user_id = 1 
group by l2.user_id

但我还读到您应该避免进行自联接。

我澄清一下,我正在寻找读取性能,写入无关紧要。 我的目标是它适用于 100 万用户,每个用户有 10 个赞。 我听取任何意见,谢谢!

【问题讨论】:

  • 你好@diez-gabriel,这是一个非常好的问题,也在这里进行了一些探索:stackoverflow.com/questions/29629903/graph-database-performance。或许您可以让这里的每个人多了解一下数据的预期大小?
  • @TsTeaTime 感谢您的文章,澄清了我需要从子图开始。我用预期的尺寸数据编辑了帖子。
  • 关于您的 Cypher 代码: 1. 除非Person 节点有可能具有一系列连续的传出LIKES 关系,否则您应该使用[:LIKE] 而不是[:LIKE*] . 2. aggregated value count(r) 很可能始终为 1,因为(使用您的数据模型)查询不应该为给定的一对 Person 节点多次返回相同的 r 列表。
  • @cybersam 你是对的,它必须是 [:LIKES] 没有 *。另一方面,count(r) 可以不同于 1。例如,如果 (Gabriel)-[: LIKES]->(BocaJuniors),则 Gabriel 到 Raul 或 Juana 有两条长度为 4 的路径。
  • 你说得对#2——我在想COUNT(DISTINCT r)。但使用COUNT(*) 可能更清楚。

标签: sql database graph neo4j


【解决方案1】:

TLDR; IMO 关系数据库会更好,因为您可以查看一件事与另一件事之间的关系,即一个人有多少喜欢(团队)。您可以轻松更新有关用户、团队或运动的元数据,而不必担心会弄乱您的分析查询。此外,您可以轻松扩展以再次添加大学、高中等运动类型,而不必担心您之前的设置可能会被搞砸。

但是,我承认我以前从未使用过图形数据库。 :)


做一个关系数据库可能看起来像这样:

我喜欢调用这些信息表,因为它们只提供特定项目的信息,有些人也称它们为参考表: 运动(Sport_ID、Sport_Name、[等]...) 运动名称,如足球、篮球等 示例视图:

╔══════════╦════════════╦═════╗
║ Sport_ID ║ Sport_Name ║ ... ║
╠══════════╬════════════╬═════╣
║        1 ║ Football   ║ ... ║
║        2 ║ Basketball ║ ... ║
║     ...  ║ ...        ║ ... ║
╚══════════╩════════════╩═════╝

Team (Team_ID, Team_Name, Home_State,[etc]...) -- 球队将是所有球队,无论他们从事何种运动类型。 示例视图:

╔═════════╦═════════════╦═════╗
║ Team_ID ║  Team_Name  ║ ... ║
╠═════════╬═════════════╬═════╣
║       1 ║ Boca Junior ║ ... ║
║       2 ║ River Plate ║ ... ║
║       3 ║ Spurs       ║ ... ║
║     ... ║ ...         ║ ... ║
╚═════════╩═════════════╩═════╝ 

User (User_ID, User_First_Name, [etc]...) -- 所有用户的特定信息都会放在这里。 示例视图:

╔═════════╦═════════════════╦═════╗
║ User_ID ║ User_First_Name ║ ... ║
╠═════════╬═════════════════╬═════╣
║       1 ║ Mario           ║ ... ║
║       2 ║ Gabriel         ║ ... ║
║       3 ║ Juana           ║ ... ║
║       4 ║ Raul            ║ ... ║
║     ... ║ ...             ║ ... ║
╚═════════╩═════════════════╩═════╝

然后您将创建关系表以在运动、团队和用户之间建立联系。

Sports_Team (Sport_ID, Team_ID) -- 在这里您可以显示哪支球队参加了哪项运动。 示例视图:

╔══════════╦═════════╦═════╗
║ Sport_ID ║ Team_ID ║ ... ║
╠══════════╬═════════╬═════╣
║        1 ║       1 ║ ... ║
║        1 ║       2 ║ ... ║
║        2 ║       3 ║ ... ║
║      ... ║     ... ║ ... ║
╚══════════╩═════════╩═════╝

Team_User_Likes (Team_ID, User_ID) -- 在这里您可以显示哪些人喜欢哪些球队参加了哪些运动。 示例视图:

╔═════════╦═════════╦═════╗
║ Team_ID ║ User_ID ║ ... ║
╠═════════╬═════════╬═════╣
║       1 ║       1 ║ ... ║
║       2 ║       2 ║ ... ║
║       2 ║       3 ║ ... ║
║       3 ║       3 ║ ... ║
║     ... ║     ... ║ ... ║
╚═════════╩═════════╩═════╝

现在,要获得用户喜欢多少团队的分数,您要做的就是:

SELECT tul.User_ID
     , COUNT(tul.Team_ID) AS Likes
  FROM team_user_likes tul
 GROUP
    BY tul.User_ID

如果您想要用户元数据,例如他们的姓名,您可以将此查询放入 CTE,然后使用用户表连接到 CTE 表。

这可能看起来和听起来很复杂,但它会更容易编辑/更新用户/团队/运动信息。您将能够使用类似数据进行一些有趣的分析,例如有多少用户喜欢/喜欢一项运动而不是另一项运动,而不必担心影响关系表,或者每项运动的哪支球队是大多数人最喜欢的。

此外,这应该很容易扩展,具体取决于您使用的关系数据库。假设您想开始添加高中、大学等运动,您可以添加一个 sport_type 表,然后创建一个 sport_sport_type 关系表来连接哪些运动是专业的或其他运动之一。 Viola,然后您可以按运动类型进行分析,而不必担心它会如何影响您之前的设置。

我更喜欢关系数据库,因为它们似乎让事情变得更整洁。话虽如此,我从未使用过图形数据库。但是考虑到你看到一件事与另一件事之间的关系,即一个人喜欢多少个团队,我的意见是你应该使用关系数据库。

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    相关资源
    最近更新 更多