精华 Neo4j官方教程:第20节,创建图数据模型
发布于 22 天前 作者 pangguoming 183 次浏览 来自 分享

教程目录 引自:https://neo4j.com/docs/getting-started/data-modeling/tutorial-data-modeling/

教程:创建图数据模型

本教程旨在帮助您根据预期用途对数据进行建模。您将使用电影示例数据集作为主要资源。

有关数据建模基础的交互式课程,请参阅 GraphAcademy


定义领域

在本教程中,您将使用电影示例数据集。领域包括电影、出演或导演电影的人,以及对电影进行评分的用户。通过这些实体之间的连接(关系),您可以发现领域中的洞察。


定义用例

在定义领域后,您需要确定应用程序的用例。换句话说,您需要回答哪些问题?

您可以列出问题来帮助确定应用程序的用例。这些问题将帮助您定义应用程序的需求以及图中必须包含的数据。

在本教程中,您的应用程序应能够回答以下问题:

  • 哪些人出演了一部电影?
  • 哪个人导演了一部电影?
  • 某人出演了哪些电影?
  • 有多少用户对一部电影进行了评分?
  • 谁是出演电影的最年轻的人?
  • 某人在电影中扮演了什么角色?
  • 根据 IMDb,某一年评分最高的电影是哪部?
  • 某演员出演了哪些剧情片?
  • 哪些用户给某部电影打了 5 分?

定义目的

在为应用程序设计图数据模型时,您可能需要数据模型和实例模型。

数据模型

数据模型描述了领域中的节点和关系,包括标签、类型和属性。它不包含任何数据,但显示了回答用例所需的信息。

在此阶段,您可以选择使用无代码工具来可视化您的计划。例如,使用 Arrows.app,您可以绘制包含节点标签、关系类型和属性的数据模型:

示例数据模型包括表示人和电影的两个节点,通过两种关系连接。 image 根据示例领域和初始问题,您可以列出初始模型中需要的信息:

  • 区分出演电影、导演电影和评分电影的人。
  • 评分的内容、数量以及提交时间。
  • 演员在电影中扮演的角色及其年龄。
  • 电影的类型。

注意,在模型中,标签、关系类型和属性键遵循特定语法。在 Cypher® 中,这些称为标识符,区分大小写,字符串值也区分大小写。

推荐的命名规范:

  • 标签:首字母大写,使用驼峰命名法(例如:PersonMovieImdbUser)。
  • 关系类型:全大写,使用下划线分隔(例如:DIRECTEDACTED_IN)。
  • 属性键:不大写,使用驼峰命名法(例如:nameuserID)。

在创建初始模型时,专注于模型的高层设计,即实体如何连接。更详细的分配信息将在“定义实体”步骤中描述。

实例模型

实例模型是存储和处理实际数据的表示。您可以使用实例模型测试用例。

要创建实例模型,您需要一些示例数据并将其加载到所选的部署中。以下是一个小型但具有代表性的数据集: image

CREATE (Apollo13:Movie {title: 'Apollo 13', tmdbID: 568, released: '1995-06-30', imdbRating: 7.6, genres: ['Drama', 'Adventure', 'IMAX']})
CREATE (TomH:Person {name: 'Tom Hanks', tmdbID: 31, born: '1956-07-09'})
CREATE (MegR:Person {name: 'Meg Ryan', tmdbID: 5344, born: '1961-11-19'})
CREATE (DannyD:Person {name: 'Danny DeVito', tmdbID: 518, born: '1944-11-17'})
CREATE (JackN:Person {name: 'Jack Nicholson', tmdbID: 514, born: '1937-04-22'})
CREATE (SleeplessInSeattle:Movie {title: 'Sleepless in Seattle', tmdbID: 858, released: '1993-06-25', imdbRating: 6.8, genres: ['Comedy', 'Drama', 'Romance']})
CREATE (Hoffa:Movie {title: 'Hoffa', tmdbID: 10410, released: '1992-12-25', imdbRating: 6.6, genres: ['Crime', 'Drama']})

建议手动使用 Cypher 添加数据以练习数据建模。


定义实体

实例模型帮助您预览数据将如何存储为节点、关系和属性。下一步是通过更多细节完善模型。

标签

应用程序用例中的主要名词在模型中表示为节点,并可用作节点标签。例如:

  • 哪些人出演了一部电影?
  • 有多少用户对一部电影进行了评分?

初始模型中的节点为 PersonMovieUser。请注意,创建模型是一个迭代过程,经过重构后,模型可能会有所不同。

节点属性

您可以使用节点属性来:

  • 定位查询的起点

    MATCH (p:Person {name: 'Tom Hanks'})-[:ACTED_IN]-(m:Movie)
    RETURN m
    
  • 遍历图

    MATCH (p:Person)-[:ACTED_IN]-(m:Movie {title: 'Apollo 13'})-[:RATED]-(u:User)
    RETURN p, u
    
  • 返回查询数据

    MATCH (p:Person {name: 'Tom Hanks'})-[:ACTED_IN]-(m:Movie)
    RETURN m.title, m.released
    

以下是一些示例用例及其查询:

用例 步骤 查询示例
哪些人出演了一部电影? 检索电影标题,返回演员姓名。 MATCH (m:Movie {title:'Hoffa'})<-[r:ACTED_IN]-(p:Person) RETURN p.name
哪个人导演了一部电影? 检索电影标题,返回导演姓名。 MATCH (m:Movie {title:'Hoffa'})<-[r:DIRECTED]-(p:Person) RETURN p.name
某人出演了哪些电影? 检索演员姓名,返回电影标题。 MATCH (p:Person {name:'Tom Hanks'})-[:ACTED_IN]->(m:Movie) RETURN m.title
谁是出演电影的最年轻的人? 检索电影标题,评估演员年龄,返回最年轻演员姓名。 MATCH (m:Movie {title:'Sleepless in Seattle'})<-[r:ACTED_IN]-(p:Person) RETURN p.name, p.born ORDER BY p.born ASC LIMIT 1
某一年 IMDb 评分最高的电影是哪部? 检索某年发布的所有电影,评估 IMDb 评分,返回评分最高的电影标题。 MATCH (m:Movie {release:date('1995')}) RETURN m.title, m.imdbRating ORDER BY m.imdbRating DESC LIMIT 1

唯一标识符

在 Cypher 中,可以创建两个具有完全相同数据的节点。然而,从数据管理和模型角度来看,不同的节点应包含不同的数据。您可以使用唯一标识符确保每个节点都是独立且可区分的实体。

例如,Movie.tmdbID 是一个很好的唯一标识符,因为数据库中可能有不同的电影具有相同的标题,但 tmdbID 属性将不同,从而充当唯一标识符。

建议通过使用唯一性约束来强制执行唯一标识符。有关更多信息,请参阅 Cypher → 创建属性唯一性约束.


关系

关系是节点之间的连接,这些连接是用例中的动词:

  • 哪些人出演了一部电影?
  • 哪些人导演了一部电影?

命名

为图中的关系选择好的名称(类型)非常重要,并尽可能具体,以便 Neo4j 仅遍历相关连接。

例如,与其使用通用的关系类型(如 CONNECTED_TO),更倾向于使用更具体且直观的方式描述实体之间的连接。

在本教程示例中,您可以定义以下关系:

  • ACTED_IN
  • DIRECTED

关系方向

所有关系必须有方向。在创建时,关系需要显式指定方向,或者通过模式的从左到右顺序推断方向。 image 在示例用例中,ACTED_IN 关系必须从 Person 节点指向 Movie 节点:

MERGE (TomH)-[:ACTED_IN]->(Apollo13)
MERGE (TomH)-[:ACTED_IN]->(SleeplessInSeattle)
MERGE (MegR)-[:ACTED_IN]->(SleeplessInSeattle)
MERGE (DannyD)-[:ACTED_IN]->(Hoffa)
MERGE (DannyD)-[:DIRECTED]->(Hoffa)
MERGE (JackN)-[:ACTED_IN]->(Hoffa)

image

关系属性

关系属性用于丰富两个节点之间的关系。当您需要知道两个节点之间的关系方式而不仅仅是它们存在关系时,可以使用关系属性进一步定义关系。 image 例如,问题“某人在电影中扮演了什么角色?”可以通过 ACTED_IN 关系中的属性 roles 来回答:

MERGE (TomH)-[:ACTED_IN {roles:'Jim Lovell'}]->(Apollo13)
MERGE (TomH)-[:ACTED_IN {roles:'Sam Baldwin'}]->(SleeplessInSeattle)
MERGE (MegR)-[:ACTED_IN {roles:'Annie Reed'}]->(SleeplessInSeattle)
MERGE (DannyD)-[:ACTED_IN {roles:'Robert "Bobby" Ciaro'}]->(Hoffa)
MERGE (JackN)-[:ACTED_IN {roles:'Hoffa'}]->(Hoffa)

查询示例:

MATCH (p:Person {name:'Tom Hanks'})-[r:ACTED_IN]->(m:Movie {title:'Apollo 13'})
RETURN r.roles

添加更多数据

现在您已经创建了节点之间的初始连接,是时候向图中添加更多信息了。例如:

  • 有多少用户对一部电影进行了评分?
  • 哪些用户给某部电影打了 5 分?

为此,您需要在图中添加用户及其评分信息,这意味着数据模型的更改。 image

添加用户节点

MERGE (Sandy:User {name: 'Sandy Jones', userID: 1})
MERGE (Clinton:User {name: 'Clinton Spencer', userID: 2})

建议将用户信息与演员和导演分开,因为它们与电影节点的关系不同。

添加评分关系

MERGE (Sandy)-[:RATED {rating:5}]->(Apollo13)
MERGE (Sandy)-[:RATED {rating:4}]->(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]->(Apollo13)
MERGE (Clinton)-[:RATED {rating:3}]->(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]->(Hoffa)

image

测试模型

在填充图以实现数据模型并使用一小组测试数据后,您现在应该测试它以确保满足每个用例。

例如,测试用例“哪些人出演了一部电影?”可以运行以下查询:

MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE m.title = 'Sleepless in Seattle'
RETURN p.name

测试时,请确保 Cypher 语句正确。错误的查询可能导致错误地认为数据模型失败。


重构

完成测试后,下一步是进行调整。有关说明,请参阅 教程:重构

回到顶部