本文简要介绍Neo4j数据库以及如何从CSV文件中导入示例数据,方便我们快速学习测试图数据库。首先介绍简单数据模型以及基本图查询概念,然后通过LOAD CSV命令导入数据,生成节点和关系。
环境准备
读者可以快速安装Neo4j Desktop,启动并创建`City Calls’项目 ,启动数据库并打开Neo4j Brower。
领域模型
领域模型非常简单,可以用三句话表达:
-
有一些城市
-
有一些人住在城市
-
人彼此通话
准备数据
图数据库与其他持久化数据库一样,可以存储数据。下面准备CSV文件数据,包括一些示例数据:
from_dt to_dt from_city from_gender from_name from_number to_city to_gender to_name to_number
2019-01-01T00:37 2019-01-01T00:44 Pattaya Woman Aleena 114-397-2007 Pattaya Woman Antonella 325-453-5419
2019-01-01T00:54 2019-01-01T01:05 Pattaya Man Jaziel 956-780-1788 Kanchanaburi Man Gabriel 469-505-9894
2019-01-01T01:01 2019-01-01T01:07 Hua Hin Woman Nayeli 320-480-8313 Kanchanaburi Woman Freya 587-595-9477
2019-01-01T01:27 2019-01-01T01:41 Bangkok Man Javier 655-683-6284 Chiang Mai Man Dalton 340-374-5681
2019-01-01T01:48 2019-01-01T01:54 Pattaya Woman Everleigh 610-164-4540 Bangkok Woman Oakley 574-752-8471
2019-01-01T02:18 2019-01-01T02:28 Chiang Mai Man Emmet 215-530-3993 Kanchanaburi Man Kareem 974-369-1496
2019-01-01T02:32 2019-01-01T02:41 Pattaya Man Henry 620-121-3009 Bangkok Man Micah 381-284-2790
2019-01-01T02:40 2019-01-01T02:54 Kanchanaburi Woman Lina 448-273-3382 Chiang Mai Man Beckham 370-171-4490
2019-01-01T03:40 2019-01-01T03:51 Pattaya Woman Alani 183-225-1764 Chiang Mai Woman Zaniyah 443-995-7423
2019-01-01T06:04 2019-01-01T06:06 Chiang Mai Woman Cassidy 959-149-3497 Bangkok Man Enrique 923-682-3283
2019-01-01T06:11 2019-01-01T06:18 Hua Hin Man Tadeo 572-552-2898 Chiang Mai Woman Gia 531-143-1961
2019-01-01T06:17 2019-01-01T06:21 Hua Hin Man Jayceon 108-826-6422 Pattaya Woman Jaelyn 283-837-9288
2019-01-01T06:42 2019-01-01T06:47 Hua Hin Woman Emerald 315-757-4272 Chiang Mai Woman Alivia 295-527-4914
2019-01-01T07:05 2019-01-01T07:09 Kanchanaburi Man Alistair 341-910-6735 Hua Hin Man Kaleb 366-100-9549
2019-01-01T07:34 2019-01-01T07:42 Bangkok Man Clark 655-643-2815 Chiang Mai Man Major 805-931-1585
2019-01-01T08:49 2019-01-01T08:56 Pattaya Man Dominick 291-616-9899 Pattaya Woman Kenna 871-427-1228
2019-01-01T09:18 2019-01-01T09:23 Bangkok Woman Aileen 413-665-7064 Pattaya Woman Brooklyn 508-151-5830
2019-01-01T09:39 2019-01-01T09:49 Hua Hin Man Manuel 523-347-6054 Bangkok Man Tobias 252-753-3307
2019-01-01T09:57 2019-01-01T10:06 Hua Hin Woman Avalyn 656-507-8932 Hua Hin Man Harlan 865-375-6184
我们看到CSV文件每行代表一次通话信息:开始时间、结束时间、人名称、性别、电话号码和城市。为了导入CSV文件至图数据库,首先应该设计图数据结构。
数据模型
CSV一行信息表示谁给谁打了电话,转换该信息至图表示,需要使用两个主要概念:节点和关系。
节点
一个节点代表张三,一个节点代表李四,两者都包括属性:姓名、性别、电话号码和城市。两个节点属于相同类型,都表示一个人,我们称节点类型为节点标签(Node Label)。我们想从行中提取的另一个节点是Call的节点,Duration属性表示呼叫开始和结束之间的分钟差。
关系
目前我们有了几个节点,但这仍然不是一个图。我们的节点之间没有关系,我们需要修复它。从张三给李四打过电话的事实来看,我们可以说张三是打出去的,我们称这种关系为外向[OUT];在另一边,李四接到了一个电话,所以对他来说,这个电话是来电[IN]。
规范化
现在在Person节点中有city属性。这种结构会导致数据重复和潜在的不一致问题。更好的设计是将每个城市作为一个独立的节点,与居住在那里的每个人建立关系。
导入数据
CSV文件可以为远程或本地。本地位置为:\ne4j-desk\data\relate-data\dbmss\dbms-***\import
, CSV文件包括头则使用 WITH HEADERS
,其他配置参考官方文档:LOAD CSV - Cypher Manual (neo4j.com)
导入脚本如下,下面进行解释说明:
LOAD CSV WITH HEADERS FROM 'file:///city_calls.csv' AS line
MERGE (c1:City { name: line.from_city })
MERGE (p1:Person{ name: line.from_name,number: line.from_number, gender: line.from_gender })
MERGE (p1)-[:FROM]->(c1)
MERGE (C2:City { name: line.to_city })
MERGE (p2:Person { name: line.to_name,number: line.to_number, gender: line.to_gender })
MERGE (p2)-[:FROM]->(c2)
CREATE (c:Call { from: datetime(line.from_dt), to: datetime(line.to_dt), duration: duration.between(datetime(line.from_dt),datetime(line.to_dt)).minutes })
CREATE (p1)-[:OUT]->(c)<-[:IN]-(p2);
从每一行CSV文件中,我们将得到1个Call节点,潜在的2个Persons节点和可能抽取2个Cities节点。为什么“可能”?因为我们不应该复制同一实体的City和Person节点,而应该只创建一次,然后重用添加更多关系的节点。图中应该仅有一个曼谷城市,所以这个“单实例”要求应该对所有城市、人员和Call节点都成立。
MERGE命令帮助我们避免节点重复。如果指定的结构(节点或节点和关系的组合)在数据库中不存在,那么将创建它,否则跳过。
到目前为止,每一行代表一个事实调用,我们需要所有的事实,我们可以简单地创建调用,没有任何重复的问题。但两次运行此脚本将导致一次又一次地创建相同的Call节点,因此不要重复导入。
查询所有节点进行确认。
MATCH(c) return c;
参考文档:https://vladbatushkov.medium.com/learn-neo4j-cypher-basics-in-30-minutes-94d68a52544