sql - 图形或关系数据库更适合这种树结构?
问题描述
我是图形数据库的新手,需要针对这种情况提出建议。我有喜欢类别的人(只有树上的叶子),其他节点(父母)没有得到“喜欢”。然后我计算特定用户与其他用户的所有连接的分数。这是一个图形示例:
我尝试使用 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 个赞。我听任何意见,谢谢!
解决方案
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,然后您可以按运动类型进行分析,而不必担心它会如何影响您之前的设置。
我更喜欢关系数据库,因为它们似乎让事情变得更整洁。话虽如此,我从未使用过图形数据库。但是考虑到你看到一件事与另一件事的关系,即一个人喜欢多少个团队,我的意见是你应该使用关系数据库。
推荐阅读
- javascript - 响应式带引导程序
- python - 熊猫如何将解析后的数据以某种格式写入文本文件
- azure - 如何设置多个时间段的cron表达式
- python - Python中的多索引循环
- javascript - 检查数组是否包含 TypeScript 中特定类的实例
- java - 如何在 Spring Kafka JsonSerializer 中注入 ObjectMapper bean?
- flutter - Flutter中更改BottomNavigationBarItem中图标显示条件时更新导航菜单
- javascript - 在 react + typescript Web 应用程序中使用一个 createSelector 返回到另一个 createSelector
- javascript - Firefox 与基于 chromium 的浏览器上的 window.history.go(-1) 不同的表单行为
- symfony - 如何使用 setcontent 过滤选定的值?