GraphGists

引言

攀岩是一项越来越受欢迎的运动,逐年增长,它无疑是户外休闲的绝佳方式,也提供了挑战自我的好机会。对我来说,它提供了源源不断的动力和放松,我相信对世界各地的许多攀岩者来说也是如此。

在这篇 gist 中,我专注于最流行的攀岩类型,即运动攀岩。从本质上讲,我们可以说运动攀岩是一种垂直方向的运动,其目标是通过使用等级系统(alpinist.com)来挑战个人的极限。运动攀岩可以进一步细分为抱石和先锋攀登。后者在大众中可能比抱石更有名。抱石除了垫子外不使用任何保护,而先锋攀登则使用绳索和其他保护设备。

毫无疑问,攀岩作为一项运动将继续增长,无论是对于像我一样的爱好者还是专业人士(希望未来能进入奥运会)

动机

这篇 gist 提供了一个应用的大纲或模型,它结合了线路和攀岩点数据库以及攀岩者可以见面和互动的社交点。关于线路、攀岩点和包含它们的国家的数据是高度互联的,就像 Neo4j 这样的图数据库的完美工作一样。它的社交方面只会增加这种想法。

在后续章节中,给出了数据模型的描述,并对术语进行了一些解释,以使读者更清楚。按照挑战赛的规则,提供了一些用例和示例(基于示例数据)。

节点描述

  • ROUTE 是攀登岩壁的路径 :),属性:名称 (name),等级 (grade)(参见上面的等级系统)

  • CRAG,有时被称为攀岩点或只是岩壁,属性:名称 (name),朝向 (orientation)(东、西、南、北)

  • COUNTRY 代表国家(英文名称),属性:名称 (name)

  • CLUB 代表攀岩俱乐部,属性:名称 (name)

  • CLIMBER 是个体攀岩者(此模型的社交方面),属性: (first name), (last name),出生日期 (date of birth)

关系描述

攀岩点 (crags) 是线路的集合。攀岩点包含线路,而线路是攀岩点的一部分。一条线路只能是一个攀岩点的一部分,但不同的线路可以有相同的名称(实际上很常见,但在同一个攀岩点中不会有两条线路名称相同)。

通常攀岩点由俱乐部管理,俱乐部负责攀岩点(有时并非如此,但在大多数情况下是这样)。俱乐部起源于不同的国家,并拥有成员,即攀岩者。

与俱乐部一样,攀岩者也来自不同的国家,并且属于(或不属于)俱乐部。线路由攀岩者攀爬(显而易见)。这为个体攀岩者提供了一种日志,也为线路提供了一些统计数据。许多攀岩者都有一个他们最喜欢去的攀岩点。

示例数据导入

为了更好地理解模型和领域,我们应该导入一些示例数据,并用一些实体代表填充图。以下是用于示例数据导入的 cypher 查询

首先是一些节点

CREATE (:CLIMBER{name:'Alice', last_name:'Wonderland', Dob:'12.12.2000'})
CREATE (:CLIMBER{name:'Bob', last_name:'Missy', Dob:'3.3.1989'})
CREATE (:CLIMBER{name:'Jack', last_name:'Chan', Dob:'5.6.2004'})
CREATE (:CLIMBER{name:'Hilary', last_name:'Hope', Dob:'8.5.1995'})
CREATE (:CLIMBER{name:'Annie', last_name:'Hork', Dob:'8.8.1945'})

CREATE (:ROUTE{name:'Hoax', grade:'6a'})
CREATE (:ROUTE{name:'Hooking', grade:'8b'})
CREATE (:ROUTE{name:'Banana', grade:'7c'})
CREATE (:ROUTE{name:'Pork_and_Beans', grade:'5a'})
CREATE (:ROUTE{name:'Traversal', grade:'4c+'})

CREATE (:CRAG{name:'Kamnitnik', orientation:'East'})
CREATE (:CRAG{name:'Rocky', orientation:'West'})
CREATE (:CRAG{name:'Big_Wall', orientation:'North'})
CREATE (:CRAG{name:'Jungle_Tree', orientation:'South'})
CREATE (:CRAG{name:'Beach_sunset', orientation:'South'})

CREATE (:CLUB{name:'AO_Kranj'})
CREATE (:CLUB{name:'Pensilvania_CC'})
CREATE (:CLUB{name:'Ljubljana_CC'})
CREATE (:CLUB{name:'Best_Climbing_Club_Ever'})
CREATE (:CLUB{name:'SUDOSK'})

CREATE (:COUNTRY{name:'Pakistan'})
CREATE (:COUNTRY{name:'Turkey'})
CREATE (:COUNTRY{name:'Slovenia'})
CREATE (:COUNTRY{name:'France'})
CREATE (:COUNTRY{name:'USA'})

现在让我们添加一些关系

  • 俱乐部的成员

MATCH (a:CLIMBER),(b:CLUB), (c:CLIMBER),(d:CLUB), (e:CLIMBER),(f:CLUB)
WHERE a.name = 'Jack' AND b.name = 'AO_Kranj' AND c.name = 'Hilary' AND d.name = 'SUDOSK' AND e.name = 'Annie' AND f.name = 'Best_Climbing_Club_Ever'
CREATE (a)-[r:is_member]->(b), (c)-[s:is_member]->(d), (e)-[t:is_member]->(f)
RETURN r, s, t;
  • 俱乐部负责哪些攀岩点

MATCH (a:CLUB),(c:CLUB),(b:CRAG),(d:CRAG)
WHERE a.name = 'AO_Kranj' AND b.name = 'Kamnitnik' AND c.name = 'SUDOSK' AND d.name = 'Rocky'
CREATE (a)-[r:is_responsible_for]->(b), (c)-[s:is_responsible_for]->(d)
  • 不同的线路属于哪些攀岩点

MATCH (a:ROUTE),(b:CRAG),(c:ROUTE),(d:CRAG),(e:ROUTE),(f:CRAG), (g:ROUTE),(h:CRAG), (k:ROUTE),(j:CRAG)
WHERE a.name = 'Hoax' AND b.name = 'Kamnitnik' AND c.name = 'Hooking' AND d.name = 'Kamnitnik' AND e.name = 'Banana' AND f.name = 'Rocky' AND g.name = 'Pork_and_Beans' AND h.name = 'Rocky' AND k.name = 'Traversal' AND j.name = 'Jungle_Tree'
CREATE (a)-[r:is_part_of]->(b),(c)-[s:is_part_of]->(d), (e)-[v:is_part_of]->(f), (g)-[t:is_part_of]->(h), (k)-[z:is_part_of]->(j)
  • 我们在哪个国家可以找到攀岩点

MATCH (a:CRAG),(b:COUNTRY), (c:CRAG),(d:COUNTRY), (e:CRAG),(f:COUNTRY), (g:CRAG),(h:COUNTRY), (k:CRAG),(j:COUNTRY)
WHERE a.name = 'Kamnitnik' AND b.name = 'Slovenia' AND c.name = 'Rocky' AND d.name = 'Turkey' AND e.name = 'Big_Wall' AND f.name = 'USA' AND g.name = 'Jungle_Tree' AND h.name = 'France' AND k.name = 'Beach_sunset' AND j.name = 'Pakistan'
CREATE (a)-[r:is_in]->(b), (c)-[s:is_in]->(d), (e)-[t:is_in]->(f), (g)-[w:is_in]->(h), (k)-[q:is_in]->(j)
  • 不同的攀岩者喜欢哪些攀岩点

MATCH (a:CLIMBER),(b:CRAG), (c:CLIMBER),(d:CRAG), (e:CLIMBER),(f:CRAG)
WHERE a.name = 'Annie' AND b.name = 'Kamnitnik' AND c.name = 'Bob' AND d.name = 'Kamnitnik' AND e.name = 'Jack' AND f.name = 'Kamnitnik'
CREATE (a)-[r:favours]->(b), (c)-[s:favours]->(d), (e)-[t:favours]->(f)
  • 攀岩者来自哪里

MATCH (a:CLIMBER),(b:COUNTRY), (c:CLIMBER),(d:COUNTRY), (e:CLIMBER),(f:COUNTRY), (g:CLIMBER),(h:COUNTRY), (k:CLIMBER),(j:COUNTRY) WHERE a.name = 'Alice' AND b.name = 'Pakistan' AND c.name = 'Bob' AND d.name = 'Turkey' AND e.name = 'Jack' AND f.name = 'Slovenia' AND g.name = 'Hilary' AND h.name = 'France' AND k.name = 'Annie' AND j.name = 'USA'
CREATE (a)-[r:comes_from]->(b), (d)-[s:comes_from]->(c), (e)-[t:comes_from]->(f), (g)-[w:comes_from]->(h), (k)-[q:comes_from]->(j)
  • 俱乐部起源于哪些国家

MATCH (a:CLUB),(b:COUNTRY),(c:CLUB),(d:COUNTRY), (e:CLUB),(f:COUNTRY), (g:CLUB),(h:COUNTRY), (j:CLUB),(k:COUNTRY)
WHERE a.name = 'AO_Kranj' AND b.name = 'Slovenia' AND c.name = 'SUDOSK' AND d.name = 'France' AND e.name = 'Pensilvania_CC' AND f.name = 'USA' AND g.name = 'Ljubljana_CC' AND h.name = 'Slovenia' AND j.name = 'Best_Climbing_Club_Ever' AND k.name = 'USA'
CREATE (a)-[r:originates_from]->(b), (c)-[s:originates_from]->(d), (e)-[t:originates_from]->(f), (g)-[w:originates_from]->(h), (j)-[q:originates_from]->(k)
  • 谁攀爬了什么

MATCH (a:CLIMBER),(b:ROUTE),(c:CLIMBER),(d:ROUTE), (e:CLIMBER),(f:ROUTE), (g:CLIMBER),(h:ROUTE), (j:CLIMBER),(k:ROUTE), (l:CLIMBER),(m:ROUTE)
WHERE a.name = 'Alice' AND b.name = 'Hoax' AND c.name = 'Jack' AND d.name = 'Hoax' AND e.name = 'Annie' AND f.name = 'Banana' AND g.name = 'Hilary' AND h.name = 'Banana' AND j.name = 'Bob' AND k.name = 'Banana' AND l.name = 'Alice' AND m.name = 'Pork_and_Beans'
CREATE (a)-[r:climbed]->(b),(c)-[s:climbed]->(d), (e)-[t:climbed]->(f), (g)-[v:climbed]->(h), (j)-[z:climbed]->(k),(l)-[q:climbed]->(m)
  • 谁认识谁

MATCH (a:CLIMBER),(b:CLIMBER),(c:CLIMBER),(d:CLIMBER), (e:CLIMBER),(f:CLIMBER), (g:CLIMBER),(h:CLIMBER), (j:CLIMBER),(k:CLIMBER), (m:CLIMBER),(n:CLIMBER)
WHERE a.name = 'Alice' AND b.name = 'Jack' AND c.name = 'Alice' AND d.name = 'Jack' AND e.name = 'Alice' AND f.name = 'Hilary' AND g.name = 'Annie' AND h.name = 'Bob' AND j.name = 'Alice' AND k.name = 'Annie' AND m.name = 'Jack' AND n.name = 'Annie'
CREATE (a)-[r:is_friends_with]->(b), (c)-[s:is_friends_with]->(d), (e)-[t:is_friends_with]->(f), (g)-[v:is_friends_with]->(h), (j)-[q:is_friends_with]->(k), (m)-[z:is_friends_with]->(n)

现在我们已经填充了数据库,并且有了一个图,我们可以在其上执行一些查询和下一部分展示的用例。为了更好地可视化,请参考下面的图表示。

用例

在这一部分,我们展示了一些可以应用于我们的图/数据的可能用例。如前所述,我们结合了数据库和社交媒体的功能。这为我们提供了广泛的可能用例(从常规的调查性查询到一些复杂的社交图谱分析)。在这里,我们提供了一些带有 Cypher 代码片段的示例,以及在更广泛的场景(更多和实际数据)下可能实现的一些想法。

一些可能的查询可能包括

  • 谁攀爬最多

MATCH (climber)-[r:climbed]->(route)
RETURN climber.name AS WHO, count(r) AS HOW_MUCH, collect(route.name) AS WHAT
ORDER BY count(r) DESC
  • 攀岩者在哪里攀爬(最常访问的攀岩点)以及谁已经访问过

MATCH (climber)-[s:climbed]->(route)-[r:is_part_of]->(crag)-[:is_in]->(country)
RETURN crag.name AS CRAG, country.name AS COUNTRY , COUNT(r) AS NUMBER_OF_VISITS, collect(climber.name) AS WHO
  • 谁负责最受欢迎(最受喜爱)的攀岩点

MATCH (climber)-[s:favours]->(crag)<-[:is_responsible_for]-(club)
RETURN crag.name AS CRAG, count(s) AS FAVOURED, club.name AS RESPONSIBILITY_OF

这些只是对这项运动感兴趣的人或应用程序的某些功能可能提出的一些可能查询。由于这里只有一些示例数据,查询和结果不是很吸引人。

让我们检查一个涉及图的社交网络维度,一些人可能称之为调查性数据科学的示例场景。我们已经通过查询发现了大多数攀岩者喜爱的攀岩点。其中还包括了喜爱该攀岩点的攀岩者列表。

MATCH (climber)-[s:favours]->(crag)-[:is_in]->(country)
RETURN crag.name AS CRAG, count(s) AS COUNT, collect(climber.name) AS WHO

通过这样做,我们发现 Annie, Jack, Bob 喜欢同一个攀岩点。通过以下查询,我们可以发现这三人来自哪里

MATCH (country1)-[t:comes_from]-(climber)-[s:favours]->(crag)-[r:is_in]->(country2)
WHERE climber.name IN ['Annie','Bob','Jack']
RETURN climber.name AS CLIMBER, country1.name AS COMING_FROM, crag.name AS LIKED , country2.name AS FROM

结果是,只有一个人来自该攀岩点所在的国家(斯洛文尼亚)。有人可能会问,为什么有人从美国 (Annie) 和/或土耳其 (Bob) 会喜欢斯洛文尼亚这样一个小国的攀岩点。

让我们看看我们的斯洛文尼亚攀岩者 Jack 的社交图。我们可能会获得一些信息。通过以下查询,我们获得了 Jack 的朋友(以及 Jack 朋友的朋友)

MATCH (country)<-[t:comes_from]-(climber)-[z:is_friends_with]->(others)-[r:is_friends_with]-(some_others) WITH country, climber, others, some_others, t, z, r
WHERE country.name = 'Slovenia'
RETURN climber.name AS CLIMBER, collect(distinct others.name) AS ONE , collect(some_others.name) AS TWO

或者我们可以只返回图的整个社交维度(我们的数据很小,所以我们可以这样做)。通过观察这一点,我们可以发现,在斯洛文尼亚喜爱同一个攀岩点的攀岩者中,实际上只有一个人来自斯洛文尼亚。其他两人与他在第一度(Annie)或第二度(Bob)上有关联。

结论

社交网络和高度互联数据的结合是使用 Neo4j 的绝佳机会。在这篇 gist 中,我们只探索了在此类应用程序中可能遇到的可能性的一小部分。示例数据很小,结果可能对每个人都不是很有趣,但随着数据的增长,探索和应用想法的可能性也会增加。我希望这篇 gist 提供了一些关于攀岩的有用信息,也许有人会真正加入我们的行列。

一如既往,使用 Neo4j、Cypher 和图真是太有趣了。

© . All rights reserved.