比利时啤酒图表 - 直接从维基百科到 GraphGist
在过去几年里,我一直都在许多不同的场合宣扬 www.neo4j.com[Neo4j] 的福音,包括聚会、会议等等。在大多数情况下,我一直在使用一个非常特别的演示,这个演示得到了极大的认可:比利时啤酒图。它最初是我个人在 Neo4j 还没有任何适当的数据导入功能时的学习体验 - 我必须通过各种各样的方法来加载图表。
当然,现在已经发生了很大的变化。我们现在拥有了很棒的数据加载功能,在这个 GraphGist 中,我想向您展示一个基于以下内容的非常棒的端到端数据加载示例:
-
一个 维基百科页面,其中包含源数据
-
一个 谷歌电子表格,它会自动从维基百科页面加载数据
-
一个 该电子表格的 CSV 导出,我们可以自动将其馈送到 Cypher 的 LOAD CSV 功能
-
一个 LOAD CSV 语句,该语句将数据加载到 Neo4j 图表中
听起来很简单?让我们一起探索一下。
将维基百科抓取到 Google 电子表格
我记得“过去的日子里”,我必须手动将 维基百科页面 上的表格复制/粘贴到电子表格中,以便将其加载到 Neo4j 中。事实证明,现在完全没有必要。在 Google 电子表格中,您现在有一个名为“ImportHTML”的函数,它允许您连接到 URL,选择一个表格,并将该表格导入到电子表格中。在 维基百科页面 上,有 27 个这样的表格(每个字母对应一个表格,再加上一个包含品牌名称不以字母开头的啤酒的表格),我们需要逐一处理。使用公式,我们可以快速加载所有这些表格,然后使用“查询”功能删除标题行。
=query({IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";2);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";3);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";4);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";5);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";6);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";7);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";8);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";9);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";10);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";11);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";12);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";13);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";14);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";15);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";16);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";17);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";18);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";19);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";20);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";21);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";22);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";23);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";24);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";25);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";26);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";27);
IMPORTHTML("https://nl.wikipedia.org/wiki/Lijst_van_Belgische_bieren";"table";28)};
"select * where Col1 <> 'Merk'";0)
非常容易。它会动态更新表格中的数据 - 所以实际上我们现在可以抓取维基百科并立即将其提供给 Neo4j 从 CSV 导出中加载。现在我们只需要将电子表格公开,以便 LOAD CSV 可以使用 URL 下载数据集,并确保酒精百分比被正确地加载为数值。
使用 LOAD CSV 加载数据
由于比利时啤酒非常多(耶!),我们需要将一个更大的数据集加载到这个 GraphGist 中 - 所以这可能需要一些时间。我们将用来将数据导入的模型非常简单

以下是数据加载查询
create index on :BeerBrand(name);
create index on :Brewery(name);
create index on :BeerType(name);
create index on :AlcoholPercentage(value);
load csv with headers from
"https://docs.google.com/spreadsheets/d/1FwWxlgnOhOtrUELIzLupDFW7euqXfeh8x3BeiEY_sbI/export?format=csv&id=1FwWxlgnOhOtrUELIzLupDFW7euqXfeh8x3BeiEY_sbI&gid=0" as csv
with csv as beercsv
where beercsv.BeerType is not null
merge (b:BeerType {name: beercsv.BeerType})
with beercsv
where beercsv.BeerBrand is not null
merge (b:BeerBrand {name: beercsv.BeerBrand})
with beercsv
where beercsv.Brewery is not null
merge (b:Brewery {name: beercsv.Brewery})
with beercsv
where beercsv.AlcoholPercentage is not null
merge (b:AlcoholPercentage {value: tofloat(replace(replace(beercsv.AlcoholPercentage,'%',''),',','.'))})
with beercsv
match (ap:AlcoholPercentage {value: tofloat(replace(replace(beercsv.AlcoholPercentage,'%',''),',','.'))}),
(br:Brewery {name: beercsv.Brewery}),
(bb:BeerBrand {name: beercsv.BeerBrand}),
(bt:BeerType {name: beercsv.BeerType})
create (bb)-[:HAS_ALCOHOLPERCENTAGE]->(ap),
(bb)-[:IS_A]->(bt),
(bb)<-[:BREWS]-(br);
数据集对于在一个图表中进行可视化来说有点大,但我们当然可以取一个包含 10 个啤酒品牌的样本及其关系
match (b:BeerBrand)
with b
limit 10
match (b)--(n)
return b,n;
让我们看一下样本
然后我们可以进行我们典型的啤酒查询
MATCH (orval:BeerBrand {name:"Orval"})
return orval;
我们再次看一下结果
或者我最喜欢的查询之一:查找“杜威尔”和“奥瓦尔”啤酒之间的路径
MATCH (duvel:BeerBrand {name:"Duvel"}), (orval:BeerBrand {name:"Orval"}),
p = AllshortestPaths( (duvel)-[*]-(orval) )
RETURN p;
它仍然是一个典型的路径查找操作的绝佳示例,它产生了有趣的“啤酒推荐” - 我总是很欣赏 :) …
将啤酒从维基百科加载到 Neo4j 中非常容易!
毫无疑问,这是我的结论。如果我回想起几年前创建这个啤酒图所花费的时间,以及现在它变得多么容易 - 这简直令人惊叹。进步,万岁!
我希望这个 gist 对您来说很有趣,并且我们很快会再见。
这个 gist 由 Rik Van Bruggen 创建
此页面是否有帮助?