想象你手里有一张巨大的城市地图。这座城市的每一栋建筑都是独立的“地标”——酒店、书店、地铁站、朋友的家。地标与地标之间,由一条条道路连接:“人民路”通向图书馆,“梧桐巷”连接咖啡馆和健身房。如果你把每个地标画成一个小圆圈,把每条道路画成一条线,这张图就是“图(Graph)”。Neo4j图数据库,就是为这种“地标-道路”式思维而生的数据库:它把真实世界里的实体(节点)和实体之间的联系(关系)原原本本地存下来,而不是硬塞进一张张互相引用的表里。你只需顺着道路走,就能在几步之内找到“朋友的朋友的收藏清单”。这篇内容,我们就用这张城市地图的视角,拆解Neo4j的节点、关系与属性建模,以及它在知识图谱、社交推荐中的真实用法。

岗位关联

学会图数据建模,你就拥有了在“关系密集”场景下设计数据结构的第二种世界观:面对社交网络、知识图谱、风控链路时,不必再疲于应付几十个 JOIN,而是顺着一条条“道路”直接走到答案面前。

目录
  1. 可视化演示
  2. 属性图模型
  3. 对比关系型数据库
  4. Cypher查询语言
  5. 索引约束机制
  6. 建模反模式
  7. 大规模与性能
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示Neo4j属性图模型的节点、关系与属性建模方式,含图遍历查询、关系型对比与知识图谱建模最佳实践。

本节配有交互动效(进入视口后自动加载,约 3KB)。

属性图数据模型 节点存储实体及属性信息 有向关系连接节点并携带属性 Graph = (Nodes, Relationships, Properties) Neo4j用属性图模型高效建模复杂关联数据

属性图模型

城市地图上,每一栋地标建筑就是最基础的元素。Neo4j把这种元素叫作节点(Node),也叫顶点。地标可以是一座酒店、一位旅客,也可以是一本出版的书。节点上贴着的介绍牌——“开业年份”“星级”“作者名字”——就是属性(Property),它以键值对的形式挂在节点上。连接地标的道路叫作关系(Relationship),例如“人民路”是一条路,“写了”也是一种关系:作者节点“写了”书节点。关系必须有方向,但不能“反向再画一条”,除非你额外定义。这四样东西——节点、关系、属性、还有给建筑贴上的“分类标签”(比如“酒店”“书店”),合在一起就是Neo4j的属性图模型(Property Graph Model)。

如果把关系型数据库想象成一座存放“档案表”的办公大楼,那属性图模型就是一张活的、可以随时沿路行走的地图。表需要预先设计好列,而图里每个地标都可以带自己的属性,哪怕彼此属性完全不同。节点通过标签(Label)区分身份:“Person“标签表示这是一位旅客,”Book“标签表示这是一本书。一个节点可以同时贴多个标签,就像同一栋楼既是”书店“又是”咖啡馆“。关系本身也可以有属性,比如”评分:5分”“时间:2024-03-01”,这相当于在道路上写下的路况笔记。

我们用数学语言概括属性图:

回到比喻中:你在城市地图上找到“老周”这位旅客(带 Person 标签的节点),他有一条“去过”的关系指向“拉萨”(Place 节点),关系上还写着“2024 年夏天”。这就是属性图最朴素的样子——地标、道路、路牌说明。理解了这一步,后续所有查询和建模都是在这张地图上问路。

G=(V, E, L, P)G = (V,\ E,\ \mathcal{L},\ \mathcal{P})
这个公式想表达:一张图 G 由四件事组成——节点集合 V、关系集合 E、标签集合 L、以及键值对属性 P。
  1. V(节点集合)V 代表全部地标(节点)的集合,是图的“地基”。
    V={v1,v2,…,vn}V = \{v_1, v_2, \dots, v_n\}
  2. E(关系集合)E 代表道路(关系)的集合,每条关系连接两个节点。
    E⊆V×VE \subseteq V \times V
  3. L(标签函数)给每个节点贴上分类标签,如 Person、Book。
    L:V→2LabelSet\mathcal{L}: V \to 2^{\text{LabelSet}}
  4. P(属性映射)把节点或关系映射到一组键值对。
    P:(V∪E)→{(k1,v1),(k2,v2),… }\mathcal{P}: (V \cup E) \to \{(k_1,v_1), (k_2,v_2), \dots\}

对比关系型数据库

用关系型数据库(如 MySQL)记录“谁是谁的朋友”,你通常建两张表:users 和 friendships。friendships 里存 user_id 与 friend_id,靠外键关联。查询“我朋友的朋友”需要两次 JOIN,查询“朋友的朋友的朋友”就需要三次 JOIN。随着关系深度增加,SQL 的关联查询会越来越长,性能也越来越差。

而图数据库的“道路”是存储设备上的原生对象。你从“我”这个节点出发,沿着 FRIEND 关系走一步就是“朋友”,走两步就是“朋友的朋友”。不需要 JOIN,只需顺着指针移动。这就是原生关系存储(Native Graph Storage)的优势:关联深度不再是噩梦。

我们可以把图数据库查询一条深链的成本形式化地理解:

那么,图数据库能完全取代关系型数据库吗?不能。如果你做的是银行转账系统,核心是“事务一致性”和“复杂聚合统计”,关系型数据库的成熟事务机制依然更稳。图数据库的甜蜜区在深链查询:社交网络、知识图谱、权限链路、风控关系网络。用城市地图的比喻说:关系型数据库是一份按字母排序的住户名册,查一个人很快,但要描述“这个人的朋友圈如何交织”却非常吃力;而图数据库天生就是为记录这种交织而生的地图。选型时,先问自己一个问题:你的业务里,“关系”本身是不是一等公民?如果是,图数据库值得考虑。

tquery≈k×thop+tlookupt_{\text{query}} \approx k \times t_{\text{hop}} + t_{\text{lookup}}
查询耗时约等于“跳数 k 乘以单跳成本”,再加一次起点查找成本。对比关系库的“每次 JOIN 都可能扫描索引或临时表”,图库的跳步是沿着磁盘上已有的关系链行走。
  1. k(跳数)k 是你要穿透的关系层数,也就是从起点到目标走了几条路。
    k=depth(a,b)k = \text{depth}(a, b)
  2. t_hop(单跳成本)从当前节点走到相邻节点的时间,图库中近乎常数。
    thop≈constt_{\text{hop}} \approx \text{const}
  3. t_lookup(起点查找成本)用索引找到起始节点的时间。
    tlookup=O(log⁡n)t_{\text{lookup}} = O(\log n)

Cypher查询语言

在城市地图上问路,你需要一种简洁的指路语言。Neo4j 的 Cypher 就是这样的语言。它长得很像 ASCII 艺术:用小括号表示节点,用方括号和箭头表示关系。比如:

这一小串符号就是在说:“找到那个人(Person 标签、name 属性为'我'),然后沿 FRIEND 关系走出去,找到所有直接朋友 f。”

Cypher 的核心动词是 MATCH(找模式)、WHERE(过滤条件)、RETURN(返回结果),配合 CREATE(创建节点或关系)。例如要找“朋友的朋友”,并限制只找“在杭州的”:

这里 [:FRIEND*1..2] 是变长路径:允许沿 FRIEND 关系走 1 到 2 跳。它就像导游说“沿着友谊路走,最多走两个路口就到”。

把这种“模式匹配”数学化:

回到地图比喻:Cypher 就是你手上那支荧光笔,在城市地图上画出“从家出发,沿友谊路走一到两个路口”的路线。Neo4j 的查询优化器会选择合适的索引作为起点,然后沿关系逐跳扩展,而不是把整张地图重新画一遍。这也是为什么面对“朋友的朋友开什么车、去过哪些城市”这类问题,Cypher 可以写得很短、跑得很快。

(a)→[:FRIEND∗1..k](b)(a) \xrightarrow{[:FRIEND*1..k]} (b)
  1. a 与 b(路径两端节点)起点与终点节点变量。
    a,b∈Va, b \in V
  2. 箭头(关系方向)表示从 a 出发,沿关系指向 b。
    →⊂E\rightarrow \subset E
  3. \*1..k(变长限定)允许路径长度为 1 到 k 跳。
    1≤len≤k1 \le \text{len} \le k
cypher1 行
(p:Person {name: "我"})-[:FRIEND]->(f)
cypher3 行
MATCH (me:Person {name: "我"})-[:FRIEND*1..2]->(fof)WHERE fof.city = "杭州"RETURN DISTINCT fof.name

索引约束机制

一座城市如果没有门牌号,找“老周的家”就得挨家挨户问。Neo4j 的索引(Index)和约束(Constraint)就是门牌号和户籍制度。CREATE INDEX 好比给地标名录按名字建了拼音索引;CREATE CONSTRAINT 则规定某些属性的值必须唯一,比如每座城市只允许一个“市民 ID”等于 10001 的人。

具体用法:

第一条约束保证:写入两条 personId 相同的 Person 节点会被拒绝,避免重复地标。第二条索引保证:按 name 查找时不必扫描全图,直接走名录。

我们可以形式化一个“唯一性约束”的含义:

用城市比喻收尾:索引是“按名字排序的地址簿”,约束是“身份证号不可重复”的户籍规则。没有索引,“找到小美”就可能变成全图扫描——比挨家挨户敲门还慢,因为每条边都要读一遍。没有约束,城市里可能出现两栋一模一样的“小美之家”,所有指向“小美”的道路都会变得混乱。所以,建模之初就要想清楚:哪些属性是实体的“身份证号”(加约束),哪些属性是高频查询条件(加索引)。

∀vi,vj∈VPerson,i=Pj⇒vi=vj\forall v_i, v_j \in V_{\text{Person}},\P_i = P_j \Rightarrow v_i = v_j
它表示:在 Person 节点集合中,如果两个节点的某个属性(如 personId)取值相同,那么它们必须是同一个节点。
  1. for all 量词对所有满足条件的节点都生效。
    ∀vi,vj\forall v_i, v_j
  2. 属性相等两个节点在约束属性上的值相同。
    Pi=PjP_i = P_j
  3. 节点等同在数据库中被视为同一个节点。
    vi=vjv_i = v_j
cypher5 行
CREATE CONSTRAINT person_id_unique IF NOT EXISTSFOR (p:Person) REQUIRE p.personId IS UNIQUE; CREATE INDEX person_name_index IF NOT EXISTSFOR (p:Person) ON (p.name);

建模反模式

地图很好用,但画地图的人也可能画错。Neo4j 建模有一些经典反模式(Anti-patterns),就像城市里修了断头路或环形迷宫。

第一个反模式:把关系类型当属性用。比如创建 [:LIKES_2024]、[:LIKES_2025] 这样带年份的关系类型。表面上方便查询“谁在 2024 年点了赞”,实际上每新增一种年份,就新增一种关系类型,图的结构不断膨胀。正确做法是保留关系类型 [:LIKES],把年份作为关系的属性。类比城市:你不会因为一条路 2024 年翻修就把路名改成“人民路2024”,而应该在路牌上写“最近翻修:2024”。

第二个反模式:无节制的深层变长路径。[:FRIEND*1..10] 看起来很酷,但在密集图里,10 跳的路径数量可能指数级爆炸。假设每人平均 100 个朋友,3 跳就有 100 万条路径。为了避免查询卡死,应该限制跳数上限,或改用更精准的路径条件。城市里最怕“所有路口都能拐弯”,导航系统也会给出道路层级和限制条件。

第三个反模式:属性放错位置。热点数据如果放在“关系”上而不是“节点”上,可能让查询变得别扭。例如把“用户上次登录时间”放在关注关系上,而不是用户节点上,每次更新都要先找到那条关系。

第四个反模式:忘记方向与命名。关系必须有明确方向,命名用动词而非名词——[:PURCHASED] 比 [:TRANSACTION] 更符合“动词即关系”的建模直觉。反模式的代价可以这样描述:

回到城市比喻:好的地图让游客一路顺利,坏的地图则让导航反复绕圈。建模时问自己:如果这个数据是真实城市的道路,这样的画法会让路人迷路吗?把时间戳放成关系类型、把深度调到 10 跳,就是在修迷宫。克制与规范,是图建模者的第一课。

Cbad model∝davgkC_{\text{bad model}} \propto d_{\text{avg}}^{k}
当平均度数(每个节点连接数)为 d_avg,查询跳数为 k 时,最坏情况下的遍历成本随跳数指数增长。
  1. d_avg(平均度数)每个节点平均有多少条关系,图的“密度”指标。
    davg=2∣E∣∣V∣d_{\text{avg}} = \frac{2|E|}{|V|}
  2. k(查询跳数)模式中允许的最大路径长度。
    k=max depthk = \text{max depth}
  3. 指数关系跳数每加一,最坏路径数按平均度数倍增。
    paths∼davgk\text{paths} \sim d_{\text{avg}}^k

大规模与性能

当城市地图大到需要分册装订,就涉及大规模图数据的管理。Neo4j 社区版是单机架构,企业版才支持集群。对超大规模数据,常见的策略是分片(Sharding):按业务维度把图切成多个子图,每个服务器负责一个区域。但图分片比表分片更棘手——关系是天然的跨界公民,切分时如果用 CUT 切法,跨分片的关系会导致查询要访问多台机器,成本极高。

把分片抽象成数学形式:

分片之外,更实际的是导入性能优化。用 LOAD CSV 批量导入时,有几点经验:文件用无引号的 UTF-8 编码;一次事务提交 1000~5000 行,而不是逐行提交;为参与匹配的节点属性提前创建约束(Neo4j 会在约束上自动建索引);不要边导入边做大规模 MATCH 定位。用城市比喻说:不要一边修路一边通车,而是先修好主干道(索引),再让车流(数据)一气呵成地开进去。

跨分片查询的代价,可以用“跨城导航”理解:如果小美在分片 A,老周在分片 B,他们之间的朋友关系必须通过网络传输,比同城查询慢一个数量级。所以分片策略要尽量保证高频查询的子图落在同一分片内——按“业务域”切分,而不是简单按 ID 取模。图数据库的规模化,本质是“让关系尽量不走远路”。

V=V1∪V2∪⋯∪Vk,Vi∩Vj=∅V = V_1 \cup V_2 \cup \cdots \cup V_k,\quad V_i \cap V_j = \varnothing
图中所有节点被划分到 k 个互不重叠的分片里。
  1. 并集覆盖每个节点至少属于一个分片。
    V=⋃i=1kViV = \bigcup_{i=1}^{k} V_i
  2. 交集为空每个节点只属于一个分片,避免重复管理。
    Vi∩Vj=∅V_i \cap V_j = \varnothing

AI 应用场景

知识图谱支撑大模型问答

阶段:知识工程 / RAG(检索增强生成)

解决的问题:大模型回答专业领域问题时容易“一本正经地胡说八道”。把领域知识构建成 Neo4j 知识图谱,用节点表示实体、关系表示语义联系后,问答系统可以先从图谱中检索出可信的实体路径,再交给大模型组织语言。传统方式靠纯向量检索,缺乏多跳推理能力;图图谱让“谁发明了 X,而 X 被用于 Y”这类链式知识可以被精确检索。

具体案例:医疗问答系统中,把“药品-适应症-禁忌-相互作用”建成图。用户问“我正在吃阿司匹林,能用布洛芬吗?”系统沿 [:与药物相互作用] 关系找到警示路径,再生成解释。相比纯文本抽取,图结构天然支持多跳解释。

社交推荐与反欺诈

阶段:特征工程 / 图特征推理

解决的问题:传统风控只看单点特征(金额、设备指纹),很难识别团伙欺诈。把用户、设备、银行卡建模为图后,通过查询“二度关联中是否有黑名单节点”,就能快速发现风险环。图模型让“关系链”成为可计算的特征,而不是离散字段。

具体案例:某电商平台把登录设备、收货地址、支付账号建成图,MATCH (u:User)-[:USED_DEVICE]->(d:Device)<-[:USED_DEVICE]-(u2:User) RETURN u2 找到共享同一设备的不同账号,命中批量注册羊毛党。

Python 演示

python56 行
class PropertyGraph:    def __init__(self):        self._nodes = {}        self._edges = []     def add_node(self, node_id, labels=None, **props):        if node_id in self._nodes:            raise ValueError("node exists")        self._nodes[node_id] = {"labels": labels or [], "props": props}     def add_edge(self, src, dst, rel_type, **props):        if src not in self._nodes or dst not in self._nodes:            raise KeyError("node not found")        self._edges.append({"src": src, "dst": dst, "type": rel_type, "props": props})     def neighbors(self, node_id, rel_type=None):        result = []        for e in self._edges:            if e["src"] == node_id and (rel_type is None or e["type"] == rel_type):                result.append(e["dst"])        return result     def bfs(self, start, rel_type=None, max_depth=2):        visited = {start: 0}        frontier = [start]        while frontier:            cur = frontier.pop(0)            if visited[cur] >= max_depth:                continue            for nxt in self.neighbors(cur, rel_type):                if nxt not in visited:                    visited[nxt] = visited[cur] + 1                    frontier.append(nxt)        return visited     def find_friends_of_friends(self, name, max_depth=2):        start = self._find_by_name(name)        dist = self.bfs(start, "FRIEND", max_depth)        return [nid for nid, d in dist.items() if 0 < d <= max_depth]     def _find_by_name(self, name):        for nid, node in self._nodes.items():            if node["props"].get("name") == name:                return nid        raise KeyError("name not found") if __name__ == "__main__":    g = PropertyGraph()    g.add_node("u1", ["Person"], name="alice", city="hangzhou")    g.add_node("u2", ["Person"], name="bob", city="shanghai")    g.add_node("u3", ["Person"], name="carol", city="hangzhou")    g.add_node("u4", ["Person"], name="dave", city="beijing")    g.add_edge("u1", "u2", "FRIEND")    g.add_edge("u2", "u3", "FRIEND")    g.add_edge("u3", "u4", "FRIEND")    print(g.find_friends_of_friends("alice"))
目的:用约 60 行 Python 实现属性图的基本能力,验证“沿关系找朋友的朋友”这一核心图遍历思想。
  1. self._nodes = {}用字典保存所有节点,键是节点 ID,值是标签与属性。
  2. find_friends_of_friends找到指定用户两跳以内的全部好友,正是社交推荐的雏形。

常见误区

误区“既然图数据库这么强,以后所有业务都用 Neo4j,MySQL 可以淘汰了。”

正解图数据库擅长深度关联查询,但在事务性、聚合统计、成熟生态上不如关系型数据库。就像城市地图适合导航,却不适合保存人口普查的汇总账本。金融账务系统要求强一致性和复杂聚合,SQL 依然是更合适的选择。

为何常见:人容易因为一个新工具在某个场景“神奇”就过度泛化。看到图查询写起来短,就忽略了事务、备份、分析型负载的真实需求。

误区“我用 `[:LIKES_2024]` 这种关系类型,查询 2024 年点赞不是更直接吗?”

正解关系类型应该描述“本质关系”,时间等维度应作为属性。[:LIKES_2024]、[:LIKES_2025] 会让图的结构不断膨胀,每加一年就要改代码。正确做法是统一 [:LIKES],把年份写到关系属性里。类似城市不会因修缮年份改路名。

为何常见:初学者容易把“查询方便”与“建模正确”混淆,图数据库的关系类型看起来只是个字符串,于是随手拼接。

误区“图数据库查十层关系都很轻松,所以我把路径长度设成 20 也没问题。”

正解图数据库的优势在“深链”但有限制的深。若每层有 100 个邻居,10 跳的理论路径数是 100 的 10 次方,任何数据库都会被爆炸路径压垮。生产环境通常限制在 3~5 跳,或使用带过滤的变长路径。

为何常见:看到演示中 3 跳查询很快,就线性外推到 10 跳,忽略了路径数是指数增长。

误区“节点就是表里的行,关系就是外键,没啥本质区别。”

正解关系在属性图中是一等公民,有独立的类型、方向和属性,存储上直接关联两个节点。而外键只是约束,真正的关联发生在查询时的 JOIN。图数据库的“顺着关系走”是物理层面的高效操作,不是逻辑层的计算。

为何常见:从关系型数据库迁移过来的人,习惯用表思维理解一切,忽视存储与访问模式的差异。

误区“MySQL 按用户 ID 分库,Neo4j 也按节点 ID 分片就行了。”

正解图分片必须考虑关系聚合。按 ID 取模会让强关联的朋友分布在不同分片,跨分片关系查询频繁访问网络。正确策略是按业务域切分,让高频查询的子图尽量落在同一个分片。

为何常见:分片经验通常来自关系型数据库,容易忽略图查询的局部性要求。

面试题

Q1. 在 Neo4j 属性图模型中,“节点”最适合类比生活中的什么事物?

单选题 · easy

  • A.城市地图上的一座地标建筑← 正确答案
  • B.建筑之间的一条道路
  • C.道路上的交通规则
  • D.一份按拼音排序的住户名录

答案:A。节点对应实体,类比地标建筑;关系对应道路,规则对应约束,名录对应索引。A 正确,B 是关系,C 是约束,D 是索引。

Q2. Cypher 查询 MATCH (a:Person)-[:FRIEND]->(b) RETURN b 中,[:FRIEND] 表示什么?

单选题 · easy

  • A.返回结果的字段名
  • B.名为 FRIEND 的关系类型← 正确答案
  • C.Person 节点的属性
  • D.数据库的名称

答案:B。方括号中是关系类型,FRIEND 是关系名。A 错在返回字段是 b,C 错在属性写在花括号里,D 与查询无关。

Q3. 关于图数据库与关系型数据库的差异,下列说法正确的是?

单选题 · mid

  • A.图数据库完全不支持事务
  • B.关系型数据库查询深链关系通常需要多次 JOIN← 正确答案
  • C.图数据库仅适合存储地图数据
  • D.关系型数据库本身就原生存储关系

答案:B。关系型数据库通过外键+JOIN 实现关联,深链查询需要多次 JOIN;图数据库原生存储关系。A 错误,Neo4j 支持事务;C 错误,适用社交、知识图谱等;D 错误,关系是逻辑计算而非原生存储。

Q4. 在 Neo4j 中,CREATE CONSTRAINT 的主要作用是什么?

单选题 · mid

  • A.为节点建立全文搜索
  • B.保证特定属性值的唯一性← 正确答案
  • C.给关系自动命名
  • D.提高磁盘写入速度

答案:B。约束用于唯一性校验,如“Person 的 personId 不可重复”。A 是全文索引,C 是命名规则,D 与约束无关。

Q5. 下列哪种建模方式属于反模式?

单选题 · mid

  • A.把年份作为关系的属性
  • B.把年份拼进关系类型名← 正确答案
  • C.为节点添加多个标签
  • D.为关系设置方向

答案:B。把 [:LIKES_2024] 这种时间戳写进关系类型,会让图结构无限膨胀。正确做法是统一的 [:LIKES] 加年份属性。A、C、D 都是良好实践。

Q6. 一个平均度数为 d 的图,查询 k 跳内所有路径时,最坏情况的路径数增长趋势是?

单选题 · hard

  • A.线性增长 O(k)
  • B.对数增长 O(log k)
  • C.指数增长 O(d^k)← 正确答案
  • D.保持不变 O(1)

答案:C。每多走一跳,可扩展的邻居数约为 d 倍,所以 k 跳路径数按 d 的 k 次方增长,这就是深层路径爆炸的原因。

Q7. 某业务需要频繁查询“用户→订单→商品→品牌”四层关系,最适合的技术选型是?

单选题 · hard

  • A.MySQL 单表加索引
  • B.Neo4j 图数据库← 正确答案
  • C.Redis 缓存
  • D.Elasticsearch 全文检索

答案:B。固定四层关系链的深链查询是图数据库的典型场景。MySQL 需要多次 JOIN 且性能随深度下降,Redis 不擅长复杂关系,ES 面向全文而非关系遍历。

Q8. 以下哪些措施可以提升 Neo4j 大规模数据导入性能?

多选题 · mid

  • A.使用 LOAD CSV 批量写入← 正确答案
  • B.为匹配字段提前创建唯一约束← 正确答案
  • C.每条数据单独提交一个事务
  • D.一次事务提交数千行← 正确答案

答案:ABD。批量导入应使用 LOAD CSV 并加大事务批次;提前建约束会附带索引,加速定位。C 错误,逐条提交事务会频繁刷盘,性能极差。

Q9. 关于图数据库分片策略,下列说法正确的有?

多选题 · hard

  • A.按业务域切分可减少跨分片查询← 正确答案
  • B.按节点 ID 均匀取模通常是最优的
  • C.跨分片关系查询代价高于同分片← 正确答案
  • D.分片可以让所有关系都留在本地

答案:AC。按业务域切分让高频相关节点同区,减少跨分区访问;跨分片查询需要网络传输,代价高。B 错误,均匀取模会割裂强关联子图;D 错误,任何分片方案都无法保证所有关系本地化。

Q10. 属性图模型中的“标签”(Label)可以理解为?

多选题 · easy

  • A.节点的分类身份← 正确答案
  • B.一个节点可以有多个标签← 正确答案
  • C.关系之间的连接方向
  • D.用来在 CREATE INDEX 中限定目标← 正确答案

答案:ABD。标签定义节点类别,如 Person 或 Book,一个节点可挂多个标签;索引可指定在带某标签的节点上建立。C 是关系方向的描述,不是标签的作用。