英国公司数据
英国公司数据
本 Neo4j 浏览器指南将引导您完成导入和查询英国公司注册、土地所有权和政治捐赠数据的过程。我们将在此过程中学习 Cypher!
在完成示例时,请务必参考Cypher 参考卡。
提纲
-
数据导入
-
使用
MATCH
进行查询 -
使用关系
-
模糊匹配
-
处理数字
-
日期
-
位置数据
-
图算法

导入
请确保在 Neo4j 浏览器中启用多语句查询编辑器,然后运行
CREATE CONSTRAINT ON (c:Company) ASSERT c.companyNumber IS UNIQUE;
//Constraint for a node key is a Neo4j Enterprise feature only - run on an instance with enterprise
//CREATE CONSTRAINT ON (p:Person) ASSERT (p.birthMonth, p.birthYear, p.name) IS NODE KEY
CREATE CONSTRAINT ON (p:Property) ASSERT p.titleNumber IS UNIQUE;
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/PSCAmericans.csv" AS row
MERGE (c:Company {companyNumber: row.company_number})
RETURN COUNT(*);
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/PSCAmericans.csv" AS row
MERGE (p:Person {name: row.`data.name`, birthYear: row.`data.date_of_birth.year`, birthMonth: row.`data.date_of_birth.month`})
ON CREATE SET p.nationality = row.`data.nationality`,
p.countryOfResidence = row.`data.country_of_residence`
// TODO: Address
RETURN COUNT(*);
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/PSCAmericans.csv" AS row
MATCH (c:Company {companyNumber: row.company_number})
MATCH (p:Person {name: row.`data.name`, birthYear: row.`data.date_of_birth.year`, birthMonth: row.`data.date_of_birth.month`})
MERGE (p)-[r:HAS_CONTROL]->(c)
SET r.nature = split(replace(replace(replace(row.`data.natures_of_control`, "[",""),"]",""), '"', ""), ",")
RETURN COUNT(*);
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/CompanyDataAmericans.csv" AS row
MATCH (c:Company {companyNumber: row.` CompanyNumber`})
SET c.name = row.CompanyName,
c.mortgagesOutstanding = toInteger(row.`Mortgages.NumMortOutstanding`),
c.incorporationDate = Date(Datetime({epochSeconds: apoc.date.parse(row.IncorporationDate,'s','dd/MM/yyyy')})),
c.SIC = row.`SICCode.SicText_1`,
c.countryOfOrigin = row.CountryOfOrigin,
c.status = row.CompanyStatus,
c.category = row.CompanyCategory;
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/ElectionDonationsAmericans.csv" AS row
MATCH (c:Company) WHERE c.companyNumber = row.CompanyRegistrationNumber
MERGE (p:Recipient {name: row.RegulatedEntityName})
SET p.entityType = row.RegulatedEntityType
MERGE (c)-[r:DONATED {ref: row.ECRef}]->(p)
SET r.date = Date(Datetime({epochSeconds: apoc.date.parse(row.ReceivedDate,'s','dd/MM/yyyy')})),
r.value = toFloat(replace(replace(row.Value, "£", ""), ",", ""));
LOAD CSV WITH HEADERS FROM "https://guides.neo4j.com/ukcompanies/data/LandOwnershipAmericans.csv" AS row
MATCH (c:Company {companyNumber: row.`Company Registration No. (1)`})
MERGE (p:Property {titleNumber: row.`Title Number`})
SET p.address = row.`Property Address`,
p.county = row.County,
p.price = toInteger(row.`Price Paid`),
p.district = row.District
MERGE (c)-[r:OWNS]->(p)
WITH row, c,r,p WHERE row.`Date Proprietor Added` IS NOT NULL
SET r.date = Date(Datetime({epochSeconds: apoc.date.parse(row.`Date Proprietor Added`,'s','dd-MM-yyyy')}));
CREATE INDEX ON :Company(incorporationDate);
验证数据导入
通过运行以下命令来验证导入的数据模型
CALL db.schema.visualization();
人员
-
姓名
-
国籍
-
居住国
-
出生年份
-
出生月份
关系
(:Person)-[:HAS_CONTROL]→(:Company)
公司
-
公司编号
-
姓名
-
状态
-
行业代码
-
原产国
-
成立日期
-
未偿抵押贷款
关系
-
(:Company)-[:OWNS]→(:Property)
-
(:Company)-[:DONATED]→(:Recipient)
房产
-
房产证号
-
地址
-
郡
-
区
-
价格
接收方
-
姓名
-
实体类型
使用 MATCH
进行查询
现在我们已经导入了数据,是时候对其进行查询了!
在 Neo4j 中,我们使用 MATCH
命令来查询数据。语法为 MATCH
,后跟一个图模式。例如
MATCH (p:Person {name: "Margery Kraus"})
RETURN p
-
()
表示一个节点 -
:Person
是节点标签 -
{}
表示属性 -
{name: ""}
-
p
成为一个变量,绑定到与模式匹配的图片段 -
我们使用
RETURN
返回数据并可视化结果
使用 MATCH
进行查询 - 练习
现在轮到你了!
-
查找名为
Michael Rubens Bloomberg
的Person
节点。 -
查找名为
GRAPHIC PLC
的Company
。
请记住 MATCH
的基本格式
MATCH (variable:NodeLabel {property: "value"})
RETURN variable
使用 MATCH
进行查询 - 答案
查找名为 Michael Rubens Bloomberg
的 Person
节点。
MATCH (p:Person {name: "Michael Rubens Bloomberg"})
RETURN p
查找名为 GRAPHIC PLC
的 Company
。
MATCH (c:Company {name: "GRAPHIC PLC"})
RETURN c
使用关系
节点通过关系连接。我们可以定义更复杂的图模式,这些模式在我们的 MATCH
语句中包含关系,使用方括号 []
来定义关系。例如
MATCH (p:Person {name: "Margery Kraus"})-[:HAS_CONTROL]->(c:Company)
RETURN p, c
-
注意
-[:HAS_CONTROL]→
模式
使用关系 - 练习
-
你能找到与 Michael Rubens Bloomberg 相关的公司吗?
-
这些与 Michael Ruben Bloomberg 相关的公司是否拥有任何房产?
-
这些与 Michael Ruben Bloomberg 相关的公司是否进行了任何政治捐款?
使用关系 - 答案
与 Michael Rubens Bloomberg 相关的公司?
MATCH (p:Person {name: "Michael Rubens Bloomberg"})-[:HAS_CONTROL]->(c:Company)
RETURN p, c
这些公司是否拥有任何房产?
MATCH (p:Person {name: "Michael Rubens Bloomberg"})-[:HAS_CONTROL]->(c:Company)-[:OWNS]->(pr:Property)
RETURN p, c, pr
这些公司是否进行了任何政治捐款?
MATCH (p:Person {name: "Michael Rubens Bloomberg"})-[:HAS_CONTROL]->(c:Company)-[:DONATED]->(r:Recipient)
RETURN p, c, r
模糊匹配
我们已经了解了如何进行精确比较,但是“模糊”匹配呢?例如,如果我们不知道 Michael Bloomberg 的中间名怎么办?或者想要考虑轻微的拼写错误?
对于非精确匹配,我们有一些选择
-
CONTAINS
字符串比较运算符 -
正则表达式
-
使用全文索引进行真正的模糊匹配
模糊匹配 - CONTAINS
CONTAINS
字符串比较运算符可用于匹配包含子字符串的字符串。
为了利用 CONTAINS
,我们需要引入 WHERE
子句。我们可以在 WHERE
子句中使用任何布尔表达式来过滤匹配项。例如
MATCH (p:Person)
WHERE p.name CONTAINS "Bloomberg"
RETURN p
模糊匹配 - 正则表达式
我们还可以使用正则表达式。
这等效于使用 CONTAINS
MATCH (p:Person)
WHERE p.name =~ ".*Bloomberg.*"
RETURN p
我们还可以进行不区分大小写的匹配
MATCH (c:Company)
WHERE c.name =~ "(?i)graphic.*"
RETURN c
请参阅正则表达式文档以获取更多示例。
模糊匹配 - 全文索引
全文索引可以帮助我们进行真正的模糊比较 - 考虑拼写错误。
首先,我们必须创建全文索引
CALL db.index.fulltext.createNodeIndex("nameIndex", ["Person"], ["name"])
然后我们可以查询它
CALL db.index.fulltext.queryNodes("nameIndex", "Peterson~")
请注意名称中的 ~
。这表示我们应该匹配搜索词的轻微拼写错误。在此处阅读有关模糊匹配查询语法的更多信息此处。
模糊匹配 - 练习
1) 包含
查找 Abigail Johnson 及其相关的任何公司。提示:数据可能包含标题前缀名称(先生、女士、小姐等),因此我们需要考虑这一点。
2) 正则表达式
我们想要查找伦敦的所有房产;但是,我们注意到 Property
节点上的 address
属性同时包含“London”和“LONDON”。编写一个使用正则表达式的查询来查找伦敦的所有 Property
节点。
模糊匹配 - 答案
1) 包含
MATCH (p:Person)-[:HAS_CONTROL]->(c:Company)
WHERE p.name CONTAINS "Abigail Johnson"
RETURN p,c
2) 正则表达式
MATCH (c:Company)
WHERE c.name =~ "(?i).*london.*"
RETURN c
处理数字
将属性值存储为数字对于回答以下问题很有用
显示所有 1,000 至 10,000 英镑之间的政治捐款
MATCH (c:Company)-[d:DONATED]->(r:Recipient)
WHERE 1000 < d.value < 10000
RETURN c,d,r
请注意,这里我们正在访问关系上的属性!
显示伦敦所有价值超过 1000 万英镑的房产,这些房产由美国人控制的公司拥有。
MATCH path=(prop:Property)<-[:OWNS]-(:Company)<-[:HAS_CONTROL]-(per:Person)
WHERE prop.price > 10000000 AND prop.address =~ "(?i).*London.*"
AND per.nationality = "American"
RETURN path
对于特定个人,他们控制的公司所做的政治捐款总额是多少?
MATCH (p:Person {name: "Ms Abigail Johnson"})-[:HAS_CONTROL]->(c:Company)-[d:DONATED]->(:Recipient)
RETURN sum(d.value) AS totalDonations, p.name AS person, c.name AS company
在这里,我们执行聚合,对在我们的模式中匹配的所有 DONATED
关系的 value
属性求和。在此处阅读有关 Cypher 中聚合函数的更多信息此处。
处理数字 - 练习
-
查找 Michael Bloomberg 控制的公司所做的竞选捐款总额。
-
这些捐款给了哪些政党?每个政党的总额是多少?
-
在与 Bloomberg 相关的公司中,哪家公司进行的竞选捐款最多?
处理数字 - 答案
查找 Michael Bloomberg 控制的公司所做的竞选捐款总额。
//Find the total value of campaign donations made by companies controlled by Michael Bloomberg.
// First be sure to find all Michael Bloombergs in the data
MATCH (p:Person)
WHERE p.name =~ "(?i).*Michael.*Bloomberg.*"
// Find all companies connected to Bloomberg and donations
MATCH (p)-[:HAS_CONTROL]->(c:Company)-[r:DONATED]->(party:Recipient)
// Aggregate the value property of all donations from these companies
RETURN sum(r.value) AS total
这些捐款给了哪些政党?每个政党的总额是多少?
MATCH (p:Person)
WHERE p.name =~ "(?i).*Michael.*Bloomberg.*"
MATCH (p)-[:HAS_CONTROL]->(c:Company)-[r:DONATED]->(party:Recipient)
// When we add party.name to the RETURN clause we group our sum aggregation by party.name
RETURN party.name, sum(r.value) AS total
ORDER BY total DESC
在与 Bloomberg 相关的公司中,哪家公司进行的竞选捐款最多?
MATCH (p:Person)
WHERE p.name =~ "(?i).*Michael.*Bloomberg.*"
MATCH (p)-[:HAS_CONTROL]->(c:Company)-[r:DONATED]->(party:Recipient)
RETURN c.name, sum(r.value) AS total
ORDER BY total DESC
日期
日期在 Neo4j 中被视为一种特殊类型,并在 Cypher 中具有自己的函数。
例如,要构造一个日期
RETURN date("2019-03-06")
我们可以像这样过滤某个日期范围内的事件
MATCH (c:Company)
WHERE date("2017-01-01") < c.incorporationDate < date("2017-01-15")
RETURN c
日期 - 答案
MATCH (c:Company)-[r:DONATED]->(party:Recipient)
WHERE Date("2016-01-01") < c.incorporationDate
RETURN c
位置数据
源数据包含地址。如果我们能够将这些地址转换为经纬度,我们就可以搜索彼此靠近的属性,搜索某个点或多边形一定范围内的属性,或者创建交互式地理数据可视化。
幸运的是,我们可以使用Neo4j的地理编码过程来实现这一点。
CALL apoc.spatial.geocodeOnce("6 Anchorage Terrace, Durham (DH1 3DL)") YIELD location, latitude, longitude
我们可以使用新的属性location
(点类型)更新Property
节点。
MATCH (p:Property) WITH p LIMIT 1
CALL apoc.spatial.geocodeOnce(p.address) YIELD location, latitude, longitude, description
SET p.location = Point({latitude: latitude, longitude: longitude})
RETURN p
注意:您需要具有数据库的写入权限。
位置数据 - 搜索
查找数据集中位于Neo4j伦敦办公室10公里范围内的属性。
MATCH path=(p:Property)<-[:OWNS]-(:Company)<-[:HAS_CONTROL]-(:Person)
WHERE distance(p.location, Point({latitude:51.5122338, longitude:-0.1180369})) < 10000
RETURN path
此页面是否有帮助?