<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>Neo4j 中文社区</title><link>http://neo4j.com.cn</link><language>zh-cn</language><description>Neo4j 中文社区</description><item><title>Neo4j 不同的存储格式（store formats）的差异</title><link>http://neo4j.com.cn/topic/69606769243e73b30c0db24b</link><guid>http://neo4j.com.cn/topic/69606769243e73b30c0db24b</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;参考官方：&lt;a href=&quot;https://neo4j.com/docs/operations-manual/5/database-internals/store-formats/&quot;&gt;https://neo4j.com/docs/operations-manual/5/database-internals/store-formats/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Neo4j 存储格式概述&lt;/h2&gt;
&lt;p&gt;Neo4j 使用不同的存储格式（store formats）来将图数据持久化到磁盘上，每种格式针对特定的性能、容量和可扩展性需求进行了优化。截至 Neo4j 5.x 版本（2026 年 1 月，5.23 版本已发布），支持的格式包括 block、aligned、standard 和 high_limit。其中，block 格式是 Neo4j 5.22 及以后版本中 Enterprise Edition 新建数据库的推荐默认格式，具有最佳性能（基于块存储和数据内联）。aligned 格式是 Community Edition 和早期 Enterprise Edition 的默认格式。standard 和 high_limit 格式自 Neo4j 5.23 起已被弃用，不推荐用于新数据库，支持将于 2029 年 11 月结束。&lt;/p&gt;
&lt;p&gt;这些格式的主要区别在于数据结构、实体容量上限、ID 分配方式、性能表现、磁盘占用以及迁移路径。以下详细说明每种格式，所有信息请以 Neo4j 官方文档（Operations Manual 5 版）的 &lt;a href=&quot;https://neo4j.com/docs/operations-manual/5/database-internals/store-formats/&quot;&gt;Store formats 章节&lt;/a&gt; 及其子页面内容为准。&lt;/p&gt;
&lt;h2&gt;1. Block 格式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;格式版本：block-block-1.1&lt;/li&gt;
&lt;li&gt;引入版本：Neo4j 5.14（5.16 正式 GA）&lt;/li&gt;
&lt;li&gt;默认使用场景：Neo4j 5.22 及以后 Enterprise Edition 新建数据库（除非通过 db.format 配置覆盖）&lt;/li&gt;
&lt;li&gt;可用版本：仅 Enterprise Edition&lt;/li&gt;
&lt;li&gt;数据结构：基于块（block）的存储，采用内联（inlining）技术。属性与节点、关系共置于块中，提升数据局部性，减少指针跳转。与基于记录（record）的格式（链表式结构）形成对比。&lt;/li&gt;
&lt;li&gt;实体容量限制：
&lt;ul&gt;
&lt;li&gt;节点：最高 2⁴⁸（约 281 万亿）&lt;/li&gt;
&lt;li&gt;关系：无限制&lt;/li&gt;
&lt;li&gt;属性：无限制&lt;/li&gt;
&lt;li&gt;标签：最高 2³¹（约 21 亿）&lt;/li&gt;
&lt;li&gt;关系类型：最高 2³⁰（约 10 亿）&lt;/li&gt;
&lt;li&gt;属性键：最高 2³¹（约 21 亿）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ID 分配：内部 ID 表示数据在存储文件中的物理位置。迁移到或从该格式时 ID 会被重新分配，可能导致外部引用 ID 的应用失效。&lt;/li&gt;
&lt;li&gt;性能表现：所有格式中最高，缓存效率高、页面故障少、I/O 操作少，适合高性能和大尺度图查询。&lt;/li&gt;
&lt;li&gt;磁盘占用：高效，开销最小。&lt;/li&gt;
&lt;li&gt;推荐使用场景：所有新 Enterprise Edition 数据库，尤其是需要高性能、可扩展性和内存效率的生产环境。&lt;/li&gt;
&lt;li&gt;迁移：可从 aligned、standard（以及有限情况下 high_limit）迁移而来。使用 neo4j-admin database migrate --to-format=“block” 离线执行，需要约 1 倍数据库大小的空闲磁盘空间，迁移后需重新填充索引。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Aligned 格式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;格式版本：record-aligned-1.1&lt;/li&gt;
&lt;li&gt;引入版本：Neo4j 5.0&lt;/li&gt;
&lt;li&gt;默认使用场景：Community Edition 数据库及 Neo4j 5.22 之前创建的 Enterprise Edition 数据库&lt;/li&gt;
&lt;li&gt;可用版本：Community 和 Enterprise Edition&lt;/li&gt;
&lt;li&gt;数据结构：基于记录，增加了对齐（alignment）优化，提升内存效率。数据以链表式结构存储，但记录带有填充以对齐边界。&lt;/li&gt;
&lt;li&gt;实体容量限制：
&lt;ul&gt;
&lt;li&gt;节点：最高 2³⁵（约 343 亿）&lt;/li&gt;
&lt;li&gt;关系：最高 2³⁵（约 343 亿）&lt;/li&gt;
&lt;li&gt;属性：最高 2³⁶（约 687 亿）&lt;/li&gt;
&lt;li&gt;标签：最高 2³¹（约 21 亿）&lt;/li&gt;
&lt;li&gt;关系类型：最高 2¹⁶（65,536）&lt;/li&gt;
&lt;li&gt;属性键：最高 2²⁴（约 1678 万）&lt;/li&gt;
&lt;li&gt;关系组：最高 2³⁵（约 343 亿）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ID 分配：ID 对应存储文件中的物理偏移。迁移时重新分配。&lt;/li&gt;
&lt;li&gt;性能表现：优于 standard，但由于链表指针跳转，仍逊于 block。&lt;/li&gt;
&lt;li&gt;磁盘占用：因对齐填充略高于 standard。&lt;/li&gt;
&lt;li&gt;推荐使用场景：Community Edition 或旧 Enterprise 数据库，适用于容量在限制内的中等负载。&lt;/li&gt;
&lt;li&gt;迁移：可迁移至 block（推荐）或 high_limit（不推荐）。过程离线且 I/O 密集。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Standard 格式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;格式版本：record-standard-1.1&lt;/li&gt;
&lt;li&gt;引入版本：Neo4j 5.0（从早期版本演进）&lt;/li&gt;
&lt;li&gt;默认使用场景：旧版本数据库，非当前默认&lt;/li&gt;
&lt;li&gt;可用版本：Community 和 Enterprise Edition&lt;/li&gt;
&lt;li&gt;弃用状态：自 Neo4j 5.23 起弃用，将在下一个 LTS 版本（预计 2026 年 11 月）后移除支持&lt;/li&gt;
&lt;li&gt;数据结构：基础记录存储，无对齐优化，纯链表式结构。&lt;/li&gt;
&lt;li&gt;实体容量限制：与 aligned 相同（节点/关系 2³⁵，属性 2³⁶ 等）&lt;/li&gt;
&lt;li&gt;ID 分配：物理位置 ID，迁移时重新分配。&lt;/li&gt;
&lt;li&gt;性能表现：基础水平，指针跳转导致较高延迟。&lt;/li&gt;
&lt;li&gt;磁盘占用：记录格式中最低。&lt;/li&gt;
&lt;li&gt;推荐使用场景：仅用于遗留兼容，不建议新建。应迁移至 block 或 aligned。&lt;/li&gt;
&lt;li&gt;迁移：可迁移至 aligned、block 或 high_limit（后者不推荐）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. High-Limit 格式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;格式版本：record-high_limit-1.1&lt;/li&gt;
&lt;li&gt;引入版本：Neo4j 5.0（从早期版本演进）&lt;/li&gt;
&lt;li&gt;默认使用场景：从不默认，必须显式指定&lt;/li&gt;
&lt;li&gt;可用版本：仅 Enterprise Edition&lt;/li&gt;
&lt;li&gt;弃用状态：自 Neo4j 5.23 起弃用，同 standard&lt;/li&gt;
&lt;li&gt;数据结构：记录格式，针对极端容量设计，使用更宽的 ID 和额外开销。&lt;/li&gt;
&lt;li&gt;实体容量限制：
&lt;ul&gt;
&lt;li&gt;节点：最高 2⁵⁰（约 1 万亿亿，即 1 quadrillion）&lt;/li&gt;
&lt;li&gt;关系：最高 2⁵⁰&lt;/li&gt;
&lt;li&gt;属性：最高 2⁵⁰&lt;/li&gt;
&lt;li&gt;标签：最高 2³¹（约 21 亿）&lt;/li&gt;
&lt;li&gt;关系类型：最高 2²⁴（约 1678 万）&lt;/li&gt;
&lt;li&gt;属性键：最高 2²⁴（约 1678 万）&lt;/li&gt;
&lt;li&gt;关系组：最高 2⁵⁰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ID 分配：更宽位分配的物理位置 ID，迁移时重新分配。&lt;/li&gt;
&lt;li&gt;性能表现：因容量开销略差于 standard。&lt;/li&gt;
&lt;li&gt;磁盘占用：所有格式中最高。&lt;/li&gt;
&lt;li&gt;推荐使用场景：仅用于超出其他格式容量的极端大图；已弃用，应迁移至 block（注意 block 容量虽高但非无限）。&lt;/li&gt;
&lt;li&gt;迁移：仅可迁移至 block（迁移前会检查是否符合 block 容量限制）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;格式对比总结表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;特性&lt;/td&gt;
&lt;td&gt;Block 格式&lt;/td&gt;
&lt;td&gt;Aligned 格式&lt;/td&gt;
&lt;td&gt;Standard 格式&lt;/td&gt;
&lt;td&gt;High-Limit 格式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据结构&lt;/td&gt;
&lt;td&gt;块存储 + 内联&lt;/td&gt;
&lt;td&gt;记录 + 对齐&lt;/td&gt;
&lt;td&gt;基础记录&lt;/td&gt;
&lt;td&gt;记录 + 高容量设计&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;最大节点数&lt;/td&gt;
&lt;td&gt;2⁴⁸（281 万亿）&lt;/td&gt;
&lt;td&gt;2³⁵（343 亿）&lt;/td&gt;
&lt;td&gt;2³⁵（343 亿）&lt;/td&gt;
&lt;td&gt;2⁵⁰（1 万亿亿）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;最大关系数&lt;/td&gt;
&lt;td&gt;无限制&lt;/td&gt;
&lt;td&gt;2³⁵（343 亿）&lt;/td&gt;
&lt;td&gt;2³⁵（343 亿）&lt;/td&gt;
&lt;td&gt;2⁵⁰（1 万亿亿）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;最大属性数&lt;/td&gt;
&lt;td&gt;无限制&lt;/td&gt;
&lt;td&gt;2³⁶（687 亿）&lt;/td&gt;
&lt;td&gt;2³⁶（687 亿）&lt;/td&gt;
&lt;td&gt;2⁵⁰（1 万亿亿）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关系类型数&lt;/td&gt;
&lt;td&gt;2³⁰（10 亿）&lt;/td&gt;
&lt;td&gt;2¹⁶（65,536）&lt;/td&gt;
&lt;td&gt;2¹⁶（65,536）&lt;/td&gt;
&lt;td&gt;2²⁴（1678 万）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;属性键数&lt;/td&gt;
&lt;td&gt;2³¹（21 亿）&lt;/td&gt;
&lt;td&gt;2²⁴（1678 万）&lt;/td&gt;
&lt;td&gt;2²⁴（1678 万）&lt;/td&gt;
&lt;td&gt;2²⁴（1678 万）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;性能&lt;/td&gt;
&lt;td&gt;最佳（低 I/O、高缓存效率）&lt;/td&gt;
&lt;td&gt;良好&lt;/td&gt;
&lt;td&gt;基础&lt;/td&gt;
&lt;td&gt;略差于 standard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;磁盘占用&lt;/td&gt;
&lt;td&gt;高效&lt;/td&gt;
&lt;td&gt;中等（对齐开销）&lt;/td&gt;
&lt;td&gt;最低&lt;/td&gt;
&lt;td&gt;最高（容量开销）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;状态&lt;/td&gt;
&lt;td&gt;活跃，Enterprise 推荐&lt;/td&gt;
&lt;td&gt;活跃，Community 默认&lt;/td&gt;
&lt;td&gt;已弃用（5.23）&lt;/td&gt;
&lt;td&gt;已弃用（5.23）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可用版本&lt;/td&gt;
&lt;td&gt;仅 Enterprise&lt;/td&gt;
&lt;td&gt;Community &amp;amp; Enterprise&lt;/td&gt;
&lt;td&gt;Community &amp;amp; Enterprise&lt;/td&gt;
&lt;td&gt;仅 Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ID 分配&lt;/td&gt;
&lt;td&gt;物理位置，迁移重分配&lt;/td&gt;
&lt;td&gt;物理位置，迁移重分配&lt;/td&gt;
&lt;td&gt;物理位置，迁移重分配&lt;/td&gt;
&lt;td&gt;物理位置，迁移重分配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可迁移目标&lt;/td&gt;
&lt;td&gt;N/A（目标格式）&lt;/td&gt;
&lt;td&gt;到 block 或 high_limit&lt;/td&gt;
&lt;td&gt;到 aligned、block 或 high_limit&lt;/td&gt;
&lt;td&gt;仅到 block&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;附加说明&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;查看当前格式：使用 Cypher SHOW DATABASES YIELD name, store 或命令行 neo4j-admin database info &amp;lt;database&amp;gt;。&lt;/li&gt;
&lt;li&gt;设置格式：新建数据库时通过 neo4j.conf 中的 db.format 配置，或在创建/导入时指定。&lt;/li&gt;
&lt;li&gt;弃用影响：standard 和 high_limit 将于 2029 年 11 月后失去支持，Enterprise 用户强烈建议迁移至 block以获得性能提升。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 09 Jan 2026 02:26:49 GMT</pubDate></item><item><title>Neo4j中的15种不同图算法及其功能</title><link>http://neo4j.com.cn/topic/68f63beca8f5aea0094a7c78</link><guid>http://neo4j.com.cn/topic/68f63beca8f5aea0094a7c78</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;图表分析在企业决策中能够发挥极大的价值，而好的图形算法不仅易于使用，执行速度快，而且能够产生强大的结果。Neo4j包含一个不断增长的开放式高性能图形算法库，可以揭示连接数据中的隐藏模式和结构。
本文将为大家介绍Neo4j中提供的诸多图算法以及它们的功能。使用Neo4j图形算法，用户可以建模并预测复杂的动态特性，例如资源或信息的流动，传染或网络故障传播的途径，以及组的影响和弹性。
由于Neo4j是将原生图平台中的分析和事务操作结合在一起，用户不仅可以揭示真实世界系统的内在本质，还可以更快地开发和部署基于图形的解决方案，并具有易于使用、简化的工作流程。&lt;/p&gt;
&lt;h2&gt;遍历和寻路算法&lt;/h2&gt;
&lt;h3&gt;1.广度优先算法(BFS)&lt;/h3&gt;
&lt;p&gt;做什么：遍历树数据结构，探索最近的邻居和他们的次级邻居。它用于定位连接，是许多其他图算法的前身。
当树较不平衡或目标更接近起点时，BFS是首选。它也可用于查找节点之间的最短路径或避免深度优先搜索的递归过程。
如何使用：广度优先搜索可用于定位像BitTorrent等对等网络中的邻居节点，GPS系统可精确定位附近的位置，社交网络服务可在特定距离内查找人员。&lt;/p&gt;
&lt;h3&gt;2.深度优先算法(DFS)&lt;/h3&gt;
&lt;p&gt;做什么：遍历树数据结构，通过在回溯之前尽可能探索每个分支。用于深层次的数据，是许多其他图算法的前身。当树较平衡或目标更接近端点时，深度优先搜索是首选。
如何使用：深度优先算法通常用于游戏模拟，其中每个选择或动作引发另一个操作，从而扩展成可能性的树形图。它将遍历选择树，直到找到最佳解决方案路径(即胜利)。&lt;/p&gt;
&lt;h3&gt;3.单源最短路径&lt;/h3&gt;
&lt;p&gt;做什么：计算节点与所有其他节点之间的路径，以及其与所有其他节点的总和值(成本，距离，时间或容量等关系的权重)并得出总和最小。
如何使用：单源最短路径通常用于自动获取物理位置之间的路线，例如通过Google地图获取驾车路线。在逻辑路由中也很重要，例如电话呼叫路由(最低成本路由)。&lt;/p&gt;
&lt;h3&gt;4.全源最短路径&lt;/h3&gt;
&lt;p&gt;做什么：计算包含图中节点之间所有最短路径的最短路径森林(组)。当最短路径被阻塞或变得次优时，切换到新的最短路径，通常用于备用路由。
如何使用：用于评估备用路由，例如高速公路备份或网络容量。它也是为逻辑路由提供多路径的关键，比如呼叫路由选择。&lt;/p&gt;
&lt;h3&gt;5.最小生成树(MWST)&lt;/h3&gt;
&lt;p&gt;做什么：计算与访问树中所有节点相关的最小值(如成本，时间或容量等关系的权重)的路径，用于逼近一些NP难题，如旅行商问题和随机或迭代舍入。
如何使用：最小生成树广泛用于网络设计：成本最低的逻辑或物理路由，如铺设电缆，最快的垃圾收集路线，供水系统容量，高效电路设计等等。它还可用于滚动优化的实时应用程序，如化学炼油厂的过程或行驶路线修正。
Centrality Algorithms&lt;/p&gt;
&lt;h3&gt;6. PageRank&lt;/h3&gt;
&lt;p&gt;做什么：估计当前节点对其相邻节点的重要性，然后再从其邻居那里获得节点的重要性。一个节点的排名来源于其传递链接的数量和质量。PageRank虽然被谷歌抛弃了，但它还是被广泛认为是检测任何网络中有影响力的节点的常用方式。
如何使用：PageRank用于评估重要性和影响力，经常的用法是推荐推特账户以及一般的情绪分析。
PageRank也用于机器学习，以确定最有影响的提取特征。在生物学中，它被用来识别食物网中哪些物种的灭绝会导致物种死亡的最大连锁反应。&lt;/p&gt;
&lt;h3&gt;7. Degree Centrality&lt;/h3&gt;
&lt;p&gt;做什么：测量节点(或整个图表)所具有的关系数量，被分为流入和流出两个方向，关系具有指向性。
如何使用：Degree Centrality着眼于用途的直接连通性，例如评估患者接近病毒或听取信息的近期风险。在社会研究中，可以用来预估人气或者其它情感。&lt;/p&gt;
&lt;h3&gt;8. Closeness Centrality&lt;/h3&gt;
&lt;p&gt;做什么：衡量一个节点对其集群内所有邻居的集中程度。假定到所有其他节点的路径都是最短的，那么该节点就能够以最快的速度到达整个组。
如何使用：Closeness Centrality适用于多种资源、交流和行为分析，尤其是当交互速度显着时。
在新公共服务中，被用于确定最大可访问性的位置。
在社交网络分析中，用于找到具有理想社交网络位置的人，以便更快地传播信息。&lt;/p&gt;
&lt;h3&gt;9. Betweenness Centrality&lt;/h3&gt;
&lt;p&gt;做什么：测量通过节点的最短路径的数量(首先通过广度优先算法找到)。出现在最短路径上次数最多的节点具有较高的介数中心性，并且是不同集群之间的桥梁。它通常与控制资源和信息的流动有关。
如何使用：Betweenness Centrality适用于网络科学中的各种问题，用于查明通信和交通网络中的瓶颈或可能的攻击目标。在基因组学中，被用于了解控制某些基因在蛋白质网络中的改进，例如更好的药物/疾病靶向。
Betweenness Centrality也被用来评估多人在线游戏玩家和共享医师专业知识的信息流。&lt;/p&gt;
&lt;h2&gt;社区发现算法&lt;/h2&gt;
&lt;p&gt;这个类别也被称为聚类算法或分区算法。&lt;/p&gt;
&lt;h3&gt;10. Label Propagation&lt;/h3&gt;
&lt;p&gt;做什么：基于邻域多数的标签作为推断集群的手段。这种极其快速的图形分割需要很少的先验信息，并且被广泛地应用于大规模的社区检测网络中。这是理解图组织的一个关键方法，通常是其他分析的主要步骤。
如何使用：Label Propagation具有不同的应用，例如了解社会团体中的共识形成、识别在生物网络的过程(功能模块)中所涉及的蛋白质集合等等。甚至还可以用于半监督和无监督的机器学习作为初始的预处理步骤。&lt;/p&gt;
&lt;h3&gt;11. Strongly Connected&lt;/h3&gt;
&lt;p&gt;做什么：定位节点组，其中每个节点可从同一组中的所有其他节点按照关系的方向到达，常被应用于深度优先算法。
如何使用：Strongly Connected通常用于在识别的集群上独立运行其他算法。作为有向图的预处理步骤，它有助于快速识别不连通的集群。
在零售推荐中，它有助于识别具有强亲和性的组，然后将向那些尚未购买商品的群体推荐首选商品。&lt;/p&gt;
&lt;h3&gt;12. Union-Find/Connected Components/Weakly Connected&lt;/h3&gt;
&lt;p&gt;做什么：查找节点组，其中每个节点可从同一组中的任何其他节点到达，而不考虑关系的方向。它提供几乎恒定的时间操作(独立于输入大小)来添加新的组，合并现有的组，并确定两个节点是否在同一组中。
如何使用：Union-find/connected 经常与其他算法结合使用，特别是对于高性能分组。作为无向图的预处理步骤，它有助于快速识别断开的组。&lt;/p&gt;
&lt;h3&gt;13. Louvain Modularity&lt;/h3&gt;
&lt;p&gt;做什么：通过比较它的关系密度与适当定义的随机网络来测量社团分组的质量(即假定的准确性)。它通常用于评估复杂网络的组织和社区层次结构。这对于无监督机器学习中的初始数据预处理也是有用的。
如何使用：Louvain用于评估Twitter，LinkedIn和YouTube上的社交结构;用于欺诈分析，以评估一个组织是只存在一些不良行为，还是背后一个连环欺诈。Louvain在比利时电信网络中揭示了一个六级客户层级。&lt;/p&gt;
&lt;h3&gt;14. Local Clustering Coefficient/Node Clustering Coefficient&lt;/h3&gt;
&lt;p&gt;做什么：对于一个特定的节点，量化了其到邻居节点的距离， (每个节点都直接连接到其他节点)。例如，如果您的所有朋友都直接了解对方，那么您的本地集群系数将是1。集群的小值表明尽管存在一个分组，但节点之间并没有紧密连接。
如何使用：Local cluster coefficient通过理解群体相关性或碎片化的可能性，对估计弹性具有重要意义。用这种方法对欧洲电网的分析发现，与稀疏连接的节点相比，集群更能抵御普遍的故障。&lt;/p&gt;
&lt;h3&gt;15. Triangle-Count and Average Clustering Coefficient&lt;/h3&gt;
&lt;p&gt;做什么：测量有多少节点具有三角形以及节点倾向于聚集在一起的程度。平均聚类系数为1时表明有一个分组，0时没有连接。为使聚类系数有意义，它应该明显高于网络中所有关系随机的版本。
如何使用：平均聚类系数通常用于估计网络是否可能展现基于紧密集群的“小世界”行为。这也是集群稳定性和弹性的一个因素。流行病学家使用平均聚类系数来帮助预测不同社区的各种感染率。&lt;/p&gt;
&lt;h2&gt;结论&lt;/h2&gt;
&lt;p&gt;世界是由关系驱动的，而Neo4j图形分析揭示了图形背后的意义，希望这些优化的图形算法能够帮助你以更加有意义、更有效的方式来理解所连接的数据。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 20 Oct 2025 13:41:00 GMT</pubDate></item><item><title>neo4j 企业版 和 社区版 对比</title><link>http://neo4j.com.cn/topic/686f1befa8f5aea0094a7c67</link><guid>http://neo4j.com.cn/topic/686f1befa8f5aea0094a7c67</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;h1&gt;Neo4j 企业版 vs 社区版对比（ 基于Neo4j 4.x）&lt;/h1&gt;
&lt;p&gt;参考官方：
&lt;a href=&quot;https://neo4j.com/docs/operations-manual/4.4/introduction/&quot;&gt;https://neo4j.com/docs/operations-manual/4.4/introduction/&lt;/a&gt;
基于Neo4j 5.x 参考官方：
&lt;a href=&quot;https://neo4j.com/docs/operations-manual/5/introduction/&quot;&gt;https://neo4j.com/docs/operations-manual/5/introduction/&lt;/a&gt;
&lt;a href=&quot;https://neo4j.com/docs/operations-manual/5/database-internals/store-formats/#high-limit-format&quot;&gt;https://neo4j.com/docs/operations-manual/5/database-internals/store-formats/#high-limit-format&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;1. 核心功能对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;功能&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;社区版&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;企业版&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;属性图模型&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原生图处理与存储&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;符合ACID原则的事务&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;密码图查询语言&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;带有语法高亮功能的Neo4j浏览器&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bolt协议&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C#、Go、Java、JavaScript和Python的语言驱动[1]&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;高性能原生API&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;高性能缓存&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基于成本的查询优化器&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;支持人工智能计划的图算法[1]&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;通过原生标签索引实现快速写入&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;组合索引&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;全文节点和关系索引&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;存储副本&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空间的自动复用&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多个数据库（超出系统和默认数据库范围）&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;槽式和流水线式Cypher运行时&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;属性存在性约束&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;节点键约束&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;列出并终止正在运行的查询&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基于角色的访问控制&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;子图访问控制&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP与Active Directory集成&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kerberos安全选项&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;2. 性能与扩展性&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;社区版&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;企业版&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;全局应用的因果集群&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;簇内加密&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;离线备份&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;在线备份&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;加密备份&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;滚动升级&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;自动缓存预热&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;使用Neo4j驱动进行路由和负载均衡&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;高级监控&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;图形大小限制&lt;/td&gt;
&lt;td&gt;340亿个节点，340亿条关系，以及680亿个属性&lt;/td&gt;
&lt;td&gt;无限制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;导入命令行工具（neo4j-admin import 命令）&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;导入命令行工具（neo4j-admin import 命令），可恢复&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️  支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;3. 安全与合规&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;社区版&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;企业版&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;角色访问控制(RBAC)&lt;/td&gt;
&lt;td&gt;❌ 仅基础用户/密码认证&lt;/td&gt;
&lt;td&gt;✔️ 细粒度权限管理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据加密&lt;/td&gt;
&lt;td&gt;❌ 仅传输加密(TLS)&lt;/td&gt;
&lt;td&gt;✔️ 传输+静态加密&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;审计日志&lt;/td&gt;
&lt;td&gt;❌ 无&lt;/td&gt;
&lt;td&gt;✔️ 完整操作记录&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP/AD集成&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;合规认证&lt;/td&gt;
&lt;td&gt;❌ 无&lt;/td&gt;
&lt;td&gt;✔️ SOC2, GDPR等&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;4. 运维与管理&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;社区版&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;企业版&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Neo4j Browser&lt;/td&gt;
&lt;td&gt;✔️ 完整功能&lt;/td&gt;
&lt;td&gt;✔️ 完整功能&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Neo4j Bloom&lt;/td&gt;
&lt;td&gt;❌ 不包含&lt;/td&gt;
&lt;td&gt;✔️ 包含可视化工具&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Neo4j Desktop&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;td&gt;✔️ 支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;官方技术支持&lt;/td&gt;
&lt;td&gt;❌ 仅社区论坛&lt;/td&gt;
&lt;td&gt;✔️ 24/7 SLA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;升级与补丁&lt;/td&gt;
&lt;td&gt;❌ 依赖社区发布&lt;/td&gt;
&lt;td&gt;✔️ 优先获取&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;5. 授权与成本&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;社区版&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;企业版&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;许可证&lt;/td&gt;
&lt;td&gt;GPLv3 开源(免费)&lt;/td&gt;
&lt;td&gt;商业许可证(按核心/年收费)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;云部署&lt;/td&gt;
&lt;td&gt;❌ 需自行部署&lt;/td&gt;
&lt;td&gt;✔️ 支持Neo4j AuraDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;商业用途&lt;/td&gt;
&lt;td&gt;✔️ 允许(需遵守GPL条款)&lt;/td&gt;
&lt;td&gt;✔️ 允许&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;6. 适用场景推荐&lt;/h2&gt;
&lt;h3&gt;选择企业版当您需要：&lt;/h3&gt;
&lt;p&gt;✅ 生产环境高可用&lt;br&gt;
✅ 企业级安全与合规&lt;br&gt;
✅ TB级大规模数据处理&lt;br&gt;
✅ 官方技术支持服务&lt;/p&gt;
&lt;h3&gt;选择社区版当您需要：&lt;/h3&gt;
&lt;p&gt;✅ 个人学习/开发测试&lt;br&gt;
✅ 小型项目(数据量&amp;lt;100GB)&lt;br&gt;
✅ 零预算的起步阶段&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;提示&lt;/strong&gt;：企业版提供30天免费试用，可通过&lt;a href=&quot;https://neo4j.com/download/&quot;&gt;官网&lt;/a&gt;申请体验完整功能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Thu, 10 Jul 2025 01:48:31 GMT</pubDate></item><item><title>Neo4j官方教程：第25节，图数据建模技巧</title><link>http://neo4j.com.cn/topic/686b8f2ea8f5aea0094a7c66</link><guid>http://neo4j.com.cn/topic/686b8f2ea8f5aea0094a7c66</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/modeling-tips/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/modeling-tips/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;图数据建模技巧&lt;/h1&gt;
&lt;h2&gt;目标&lt;/h2&gt;
&lt;p&gt;在本指南中，您将找到一些有助于为您的领域设计数据模型的实用信息。优化模型可以帮助开发人员最大化系统和查询的性能。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;建模技巧和方法&lt;/h2&gt;
&lt;p&gt;正如您在阅读建模指南或自己进行图数据建模时可能发现的那样，没有绝对正确或错误的建模方式。一些方式可能更适合您的需求，并在您优先考虑的方面表现更好，但您有多种选择。&lt;/p&gt;
&lt;p&gt;为了找到最适合您需求的数据模型，通常可以采用一些技术并根据分析结果做出数据模型决策。接下来的段落中，我们将讨论一些建模技巧和方法，帮助您选择适合的数据模型。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;1. 先编写查询&lt;/h3&gt;
&lt;p&gt;了解您希望从数据中提出的问题和查询类型，是确定数据模型结构的绝佳方法。如果您知道查询需要在特定日期范围内返回结果，那么您可能需要确保日期不是节点上的属性，而是存储为单独的节点或关系。相比之下，对于大学课程领域，寻找与当前课程类似的课程可能更适合使用高层次的类别层次结构，这样可以更高效地搜索主题内的所有课程。&lt;/p&gt;
&lt;p&gt;即使您尚未确定确切的查询语法，理解您正在构建的系统或应用程序的意图，并围绕业务需求构建模型，将帮助您以更准确的方式组织数据。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2. 优先考虑查询&lt;/h3&gt;
&lt;p&gt;找到适合每个查询或功能的完美模型是非常困难的（甚至是不可能的）。正如我们在建模设计指南中讨论的那样，选择一种特定模型而不是另一种（或使用多种模型）会有权衡。虽然您可能会改善某些方面，但无法获得适合所有情况的解决方案。&lt;/p&gt;
&lt;p&gt;相反，您应该确定哪个模型最适合您的需求。您可能无法在每个单独查询上都达到性能最大化，但您可以通过某些资源、时间和代码从系统中获得最大收益。&lt;/p&gt;
&lt;p&gt;为此，您需要决定哪些查询必须绝对具有最高性能，以及哪些功能对于提供价值至关重要。这可能是一个艰难的决定，但无论您使用哪种技术，这些决策都会以某种形式存在。Neo4j 的优势在于其模型灵活性，可以随着优先级的变化进行调整。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3. 测试模型&lt;/h3&gt;
&lt;p&gt;在设计阶段，您可能会遇到未意识到的场景。找到这些场景的最佳方法之一是实际测试模型。&lt;/p&gt;
&lt;p&gt;加载部分数据并在系统上执行测试和查询，可以确定您收到的结果是否符合您的需求或预期性能。同样，Neo4j 的灵活性使您可以调整模型或优化查询以微调输出。&lt;/p&gt;
&lt;p&gt;在多个模型之间难以决定？尝试为每个模型创建概念验证测试，并同时测试它们的运行情况。哪些模型复杂或不值得麻烦？是否有一个模型在实际运行中表现更好，或者多数据模型方法是否真正提供了最佳结果？有时，找到答案的最佳方法是使用实时数据进行测试。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;4. 重构图模型&lt;/h3&gt;
&lt;p&gt;如上所述以及其他指南中提到的，使用 Neo4j 时始终可以进行更改。数据模型设计为灵活且易于调整，正是出于这个原因。业务需求和优先级往往会波动。用户行为也可能发生变化，从而导致业务的转变。&lt;/p&gt;
&lt;p&gt;Cypher® 允许您编写查询以对标签进行批量更新、添加或删除属性，以及向结构中插入额外的节点和关系。此外，还有一些程序可以帮助批量查询和更新集群实例。&lt;/p&gt;
&lt;p&gt;有关此主题的更多信息，请查看 &lt;a href=&quot;https://neo4j.com/labs/apoc/&quot;&gt;APOC 库&lt;/a&gt;！&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;其他注意事项&lt;/h3&gt;
&lt;p&gt;数据集的大小也会影响查询和性能。如果您的数据集较小，那么在执行更复杂的查询时可能不会看到太大的性能影响。只有当数据量增长时，您才可能看到影响增加。这时，数据模型和查询优化对于最大化系统价值变得至关重要。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 07 Jul 2025 09:11:10 GMT</pubDate></item><item><title>Neo4j官方教程：第24节，从关系型数据模型到图数据模型的建模</title><link>http://neo4j.com.cn/topic/686b8eaaa8f5aea0094a7c65</link><guid>http://neo4j.com.cn/topic/686b8eaaa8f5aea0094a7c65</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/relational-to-graph-modeling/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/relational-to-graph-modeling/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;从关系型数据模型到图数据模型的建模&lt;/h1&gt;
&lt;p&gt;对于有关系型数据建模背景的人来说，本指南将帮助您将现有的关系型数据建模知识转化为图数据建模知识。它将帮助您比较和对比两种建模过程的步骤，并帮助您识别两种数据库类型在数据建模方面的相似点和不同点。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;简介&lt;/h2&gt;
&lt;p&gt;如果您熟悉关系型数据模型（包括表、列、关系基数等组件），那么图数据建模不会显得完全陌生。数据模型的设计仍然需要基于访问需求、查询需求、性能预期和业务逻辑。然而，图数据模型的结构略有不同。&lt;/p&gt;
&lt;p&gt;您可能有一个全新的项目，想要创建图数据模型，但只熟悉如何创建关系型模型。或者您可能已经有一个现有的关系型模型项目，想要将其转换为图模型。无论哪种情况，本指南都将利用您对关系型数据模型的现有知识，教您如何创建图数据模型。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;关系型与图数据库架构&lt;/h2&gt;
&lt;p&gt;快速回顾一下，关系型数据库依赖索引查找和表连接来连接不同的实体。这在性能方面很快会成为问题，尤其是当有多个表连接、表中有数百万行或查询复杂且需要通过子查询遍历多个层级时。&lt;/p&gt;
&lt;p&gt;在概念页面的示例中，要找到 Alice 所属的部门，您需要查询 &lt;code&gt;Person&lt;/code&gt; 表以找到代表 Alice 的行，该行与唯一 ID（主键）绑定。然后，查询需要访问关联实体表（&lt;code&gt;Person_Dept&lt;/code&gt;），以找到她的 ID 与一个或多个部门 ID 的关联。最后，查询需要检查 &lt;code&gt;Department&lt;/code&gt; 表，以找到关联实体表中部门 ID 的实际值。&lt;/p&gt;
&lt;p&gt;下图回顾了我们刚刚描述的示例：&lt;/p&gt;
&lt;h3&gt;关系型模型示例&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_model.svg&quot; alt=&quot;image&quot;&gt;
&lt;strong&gt;图 1. 关系型模型 - &lt;code&gt;Person&lt;/code&gt; 和 &lt;code&gt;Department&lt;/code&gt; 表&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在图数据库中，您无需担心表连接和索引查找，因为图数据是通过每个单独实体及其与其他实体的关系来构建的。&lt;/p&gt;
&lt;p&gt;那么，我们如何从创建关系型数据模型转向图数据模型呢？&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;数据模型转换技巧&lt;/h2&gt;
&lt;p&gt;以下是将关系型数据模型的关键组件转换为图数据模型组件的一些技巧。帮助您将关系型图表转换为图模型的步骤如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;表到节点标签&lt;/strong&gt; - 关系型模型中的每个实体表变成图模型中的节点标签。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行到节点&lt;/strong&gt; - 关系型实体表中的每一行变成图中的一个节点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;列到节点属性&lt;/strong&gt; - 关系型表中的列（字段）变成图中的节点属性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;仅保留业务主键&lt;/strong&gt; - 删除技术主键，仅保留业务主键。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;添加约束/索引&lt;/strong&gt; - 为业务主键添加唯一约束，为频繁查找的属性添加索引。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;外键到关系&lt;/strong&gt; - 将指向其他表的外键替换为关系，然后删除外键。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;移除默认值&lt;/strong&gt; - 删除具有默认值的数据，无需存储这些值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;清理数据&lt;/strong&gt; - 去除规范化表中的重复数据，将其提取到单独的节点以获得更清晰的模型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;索引列到数组&lt;/strong&gt; - 索引列名（如 &lt;code&gt;email1&lt;/code&gt;, &lt;code&gt;email2&lt;/code&gt;, &lt;code&gt;email3&lt;/code&gt;）可能表示数组属性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;连接表到关系&lt;/strong&gt; - 连接表转换为关系，表中的列变成关系属性。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果将上述列表中的项目应用到我们寻找 Alice 所属部门的示例中，我们可以得到如下图所示的图模型：&lt;/p&gt;
&lt;h3&gt;图模型示例&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_graph_model-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;strong&gt;图 2. 图模型 - Alice 和三个部门作为节点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;虽然两种模型都有类似之处，例如通过表结构或标签对数据进行分类，但图模型不会将数据限制在预定义的严格表/列布局中。我们将在下一节中查看另一个示例。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;组织领域数据模型&lt;/h2&gt;
&lt;p&gt;为了让我们有另一个练习机会，我们将使用一个标准的组织领域，并展示它在关系型数据库和图数据库中的建模方式。您可以尝试自己创建图数据模型，然后看看它与示例模型的相似程度。&lt;/p&gt;
&lt;h3&gt;关系型组织结构图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_org_chart.svg&quot; alt=&quot;image&quot;&gt;
&lt;strong&gt;图 3. 组织领域 - 关系型模型&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;转换步骤&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;首先，我们可以通过颜色将表分类为主域表和关联实体表。然后，我们可以将表名转换为节点标签。在这种情况下，&lt;code&gt;Project&lt;/code&gt;、&lt;code&gt;Person&lt;/code&gt;、&lt;code&gt;Department&lt;/code&gt; 和 &lt;code&gt;Organization&lt;/code&gt; 成为图模型中的标签。&lt;/li&gt;
&lt;li&gt;表中的行变成它们自己的节点，行中的列变成节点上的属性。例如，&lt;code&gt;Person&lt;/code&gt; 表中的一行将变成一个节点，节点上的属性包括姓名和出生日期。任何允许多个相似值的索引列将变成数组（例如 &lt;code&gt;skill1&lt;/code&gt;, &lt;code&gt;skill2&lt;/code&gt;, &lt;code&gt;skill3&lt;/code&gt; 列转换为节点上的数组属性）。&lt;/li&gt;
&lt;li&gt;如果有任何技术主键（即仅为了使行唯一而创建的主键，例如 &lt;code&gt;project_id&lt;/code&gt;），则删除这些主键，仅保留业务需求所需的属性。还需要为业务主键添加唯一约束，以确保数据库不会允许重复。&lt;/li&gt;
&lt;li&gt;外键用于关系型连接查找的，转换为关系，因为它们显示了节点之间的链接。连接表（或关联实体表）也变成关系，连接表中的列移动到关系属性。&lt;/li&gt;
&lt;li&gt;由于 Neo4j 仅存储所需属性，因此无需存储空值和默认值，因此可以删除关系型模型中创建的任何默认值。&lt;/li&gt;
&lt;li&gt;最后，任何为规范化表或为简化而去规范化创建的重复数据都需要删除，因为在图模型中不需要这些数据。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;经过此过程后，您的图数据模型应类似于下图所示：&lt;/p&gt;
&lt;h3&gt;图组织结构图&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;图 4. 组织领域 - 图模型&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;在开始导入数据之前，了解图模型的基本概念非常重要，因为随着需求的变化，调整模型或填充模型会变得更加容易。在即将发布的指南中，您将看到图数据的建模如何影响查询、性能和模型变化。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 07 Jul 2025 09:08:58 GMT</pubDate></item><item><title>Neo4j官方教程：第23节，版本控制</title><link>http://neo4j.com.cn/topic/686b8d6da8f5aea0094a7c64</link><guid>http://neo4j.com.cn/topic/686b8d6da8f5aea0094a7c64</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/versioning/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/versioning/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;版本控制&lt;/h1&gt;
&lt;p&gt;每次重构数据模型时，都会创建新的版本。跟踪数据结构的变化或显示当前和过去的值对于审计目的、趋势分析等非常有价值。本页面概述了可以用来跟踪随时间变化的数据的不同建模方式。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;实体的版本控制&lt;/h2&gt;
&lt;p&gt;通过对相关实体进行版本控制，可以跟踪数据的变化。这种策略在以下情况下非常有用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;访问图中特定实体（例如节点）的多个版本（例如产品在不同时间的名称）。&lt;/li&gt;
&lt;li&gt;仅检索最新版本（例如产品的当前名称）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/versioned-entities.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;示例：图中显示实体的不同版本，其属性值随时间变化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;实体版本控制的特点：&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;实体 &lt;code&gt;Product&lt;/code&gt; 通过显式关系链接到其不同版本。&lt;/li&gt;
&lt;li&gt;实体 &lt;code&gt;Product&lt;/code&gt; 是不可变的。只有存储在不同版本（&lt;code&gt;State&lt;/code&gt; 节点）中的属性会发生变化。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LATEST&lt;/code&gt; 关系将实体 &lt;code&gt;Product&lt;/code&gt; 链接到其最新版本（&lt;code&gt;State&lt;/code&gt;），该版本也是版本 2（&lt;code&gt;V2&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;优缺点&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;建模、查询和维护简单。&lt;/td&gt;
&lt;td&gt;更新节点需要删除 &lt;code&gt;LATEST&lt;/code&gt; 关系，并创建实体与其最新版本之间的新关系。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;对最终用户显式，无需任何转换。&lt;/td&gt;
&lt;td&gt;如果不使用其他版本控制模式，可能会受到限制，因为如果不是最新版本，可能很难知道要检索哪个版本。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;查询示例&lt;/h3&gt;
&lt;p&gt;以下是使用实体版本控制策略的常见查询示例：&lt;/p&gt;
&lt;h4&gt;获取 ID 为 ‘1’ 的产品版本 2 的名称&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Product {id:1})-[:V2]-&amp;gt;(s:State)
RETURN s.name
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;获取 ID 为 ‘1’ 的产品最新版本的名称&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Product {id:1})-[:LATEST]-&amp;gt;(s:State)
RETURN s.name
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;基于时间的实体版本控制&lt;/h2&gt;
&lt;p&gt;实体版本控制的一种变体是基于时间的方法。这在以下情况下非常有用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;图快照&lt;/strong&gt;：通过检索图中某个时间点的所有有效元素（节点和关系）（例如，2023 年 6 月 12 日星期一可用的产品）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图差异&lt;/strong&gt;：比较两个不同时间戳的图快照（例如，哪些节点被添加、哪些被删除、哪些保持不变）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时间序列遍历&lt;/strong&gt;：仅遍历图中某个时间点的有效元素（节点或关系），以找到连接基于时间事件的关系的时间顺序（例如，带有车站之间的行程关系的共享单车图）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图历史&lt;/strong&gt;：建模数据变化的历史。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/time-based-entities.svg&quot; alt=&quot;image&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例：基于时间的实体版本控制&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基于时间的版本控制特点：&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;每个元素都有专门的 &lt;code&gt;validFrom&lt;/code&gt;/&lt;code&gt;validTo&lt;/code&gt; 时间属性。&lt;/li&gt;
&lt;li&gt;节点只有在其有效时间范围重叠时才能共享关系。&lt;/li&gt;
&lt;li&gt;信息可能会重复。&lt;/li&gt;
&lt;li&gt;图的完整历史可用。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;优缺点&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;每个元素都有明确的时间间隔，在该时间间隔内元素有效。&lt;/td&gt;
&lt;td&gt;如果节点状态发生变化，节点必须被复制，并分配新的有效时间间隔。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;状态绑定到特定元素（无需额外关系）。&lt;/td&gt;
&lt;td&gt;更新节点需要创建连接到新节点/状态的新关系，并分配新的有效时间间隔。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可以聚合所有元素（或某个时间点的有效元素）。&lt;/td&gt;
&lt;td&gt;数据重复无法避免。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;查询示例&lt;/h3&gt;
&lt;p&gt;以下是使用基于时间的实体版本控制策略的常见查询示例：&lt;/p&gt;
&lt;h4&gt;获取产品 “Rice Cooker” 的当前价格&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.name = &amp;quot;Rice Cooker&amp;quot; AND p.validTo = ∞
RETURN p.price
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;获取产品 “Rice Cooker” 在 11 月的价格&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.name = &amp;quot;Rice Cooker&amp;quot;
AND datetime(p.validFrom) &amp;lt;= datetime(&amp;quot;November&amp;quot;) &amp;lt;= datetime(p.validTo)
RETURN p.price
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;获取当前产品目录及价格&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH ()-[r:HAS_PRODUCT]-&amp;gt;(p)
WHERE r.validTo = ∞
RETURN p.name, p.price
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;链表&lt;/h2&gt;
&lt;p&gt;链表是一种建模策略，当对象的顺序很重要时非常有用。&lt;/p&gt;
&lt;h3&gt;链表的用途：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;事件顺序，例如获取银行账户执行的交易顺序。&lt;/li&gt;
&lt;li&gt;基于关系获取列表中的前一个和下一个元素（例如播放列表中的下一首歌曲，或撤销文本文档中的操作）。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/linked-list-versioning.svg&quot; alt=&quot;image&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例：使用链表模型设计进行版本控制&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;链表特点：&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;实体 &lt;code&gt;Product&lt;/code&gt; 链接到序列的第一个元素，也可以链接到最后一个元素。&lt;/li&gt;
&lt;li&gt;与实体版本控制一样，实体 &lt;code&gt;Product&lt;/code&gt; 在此处也是不可变的。&lt;/li&gt;
&lt;li&gt;序列中的每个元素通过 &lt;code&gt;NEXT&lt;/code&gt; 关系链接到下一个元素。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;优缺点&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;使用关系获取下一个/前一个元素效率高。&lt;/td&gt;
&lt;td&gt;如果不使用其他版本控制模式，可能仅限于非常具体的用例。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;建模和维护简单。&lt;/td&gt;
&lt;td&gt;很难找到不是第一个或最后一个的特定版本。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;对最终用户显式。&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;查询示例&lt;/h3&gt;
&lt;p&gt;以下是使用链表版本控制策略的常见查询示例：&lt;/p&gt;
&lt;h4&gt;获取产品 “Professional chair” 的下一个名称&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:State{name: &amp;quot;Professional chair&amp;quot;})-[:NEXT]-&amp;gt;(s:State)
RETURN s.name
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;获取 ID 为 ‘1’ 的产品的前一个名称&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Product {id:1})-[:LAST]-&amp;gt;(:State)&amp;lt;-[:NEXT]-(s:State)
RETURN s.name
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;时间线树&lt;/h2&gt;
&lt;p&gt;如建模设计中所述，时间线树是一种常见的建模设计。当您想要跟踪变化时，它可以是一种有用的策略。在此示例中，时间线结构从年份扩展到天，其余的非时间数据节点是图中包含重要数据的节点。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/timeline-tree.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;示例：图中显示两个不同的时间线按年份划分&lt;/h3&gt;
&lt;h4&gt;查询示例&lt;/h4&gt;
&lt;p&gt;如果您想找到某个时间段内发生的所有购买，例如 2012 年 12 月的所有购买，可以从 2012 年导航到 12 月，然后从该分支下的所有叶节点（没有后代的节点）中获取数据：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (root:Timeline)-[:IN_YEAR]-&amp;gt;(year:Year {value:2012})-[:IN_MONTH]-&amp;gt;(month:Month {value:12})
WITH month
MATCH (month)-[:ON_DAY]-&amp;gt;(day)
MATCH (purchase:Purchase)-[:OCCURRED]-&amp;gt;(day)
RETURN purchase
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;组合方法&lt;/h2&gt;
&lt;p&gt;一些复杂的用例需要结合上述一种或多种建模技术，因为每种技术都有其优点和缺点。&lt;/p&gt;
&lt;h3&gt;示例：结合时间线树的更复杂版本控制方法&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;具体组合取决于用例。&lt;/li&gt;
&lt;li&gt;应考虑查询时间和事务频率等因素。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 07 Jul 2025 09:03:41 GMT</pubDate></item><item><title>Langchain + deepseek +neo4j 构建电影知识图谱智能问答</title><link>http://neo4j.com.cn/topic/6833c811b13f67342db8ad6c</link><guid>http://neo4j.com.cn/topic/6833c811b13f67342db8ad6c</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;h3&gt;安装LangChain 依赖&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-shell&quot;&gt;&lt;code&gt;pip install --upgrade --quiet  langchain langchain-community langchain-openai neo4j
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;安装Neo4j&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://neo4j.com/deployment-center/&quot;&gt;https://neo4j.com/deployment-center/&lt;/a&gt; 下载安装 neo4j-community-5.26.4 解压到任意目录&lt;/p&gt;
&lt;h3&gt;安装Neo4j Apoc 插件&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/neo4j/apoc/releases?page=1&quot;&gt;https://github.com/neo4j/apoc/releases?page=1&lt;/a&gt; 下载安装apoc-5.26.6-core.jar
复制到neo4j安装目录 plugins目录下
修改Neo4j配置文件，启用Neo4j Apoc 插件：到neo4j安装目录 plugins目录下修改\conf\neo4j.conf，添加如下两行&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;dbms.security.procedures.unrestricted=apoc.*
dbms.security.procedures.allowlist=apoc.*
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;启动Neo4j&lt;/h3&gt;
&lt;p&gt;命令行到neo4j安装目录\bin下运行：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-shell&quot;&gt;&lt;code&gt;neo4j console
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;langchain + deepseek +neo4j 构建电影知识图谱智能问答&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language- python&quot;&gt;&lt;code&gt;import getpass
import os
from langchain.chains import GraphCypherQAChain
from langchain_openai import ChatOpenAI
from langchain_community.graphs import Neo4jGraph

os.environ[&amp;quot;OPENAI_API_KEY&amp;quot;] = &amp;quot;您的DeepSeek API 秘钥&amp;quot;
os.environ[&amp;quot;NEO4J_URI&amp;quot;] = &amp;quot;bolt:&amp;#x2F;&amp;#x2F;localhost:7687&amp;quot;
os.environ[&amp;quot;NEO4J_USERNAME&amp;quot;] = &amp;quot;neo4j&amp;quot;
os.environ[&amp;quot;NEO4J_PASSWORD&amp;quot;] = &amp;quot;您的Neo4j密码&amp;quot;

llm = ChatOpenAI(
    model=&amp;#x27;deepseek-chat&amp;#x27;,
    base_url=&amp;quot;https:&amp;#x2F;&amp;#x2F;api.deepseek.com&amp;#x2F;v1&amp;quot;
)

graph = Neo4jGraph()

# Import movie information

movies_query = &amp;quot;&amp;quot;&amp;quot;
LOAD CSV WITH HEADERS FROM 
&amp;#x27;https:&amp;#x2F;&amp;#x2F;raw.githubusercontent.com&amp;#x2F;tomasonjo&amp;#x2F;blog-datasets&amp;#x2F;main&amp;#x2F;movies&amp;#x2F;movies_small.csv&amp;#x27; 
AS row
MERGE (m:Movie {id:row.movieId})
SET m.released = date(row.released),
    m.title = row.title,
    m.imdbRating = toFloat(row.imdbRating)
FOREACH (director in split(row.director, &amp;#x27;|&amp;#x27;) | 
    MERGE (p:Person {name:trim(director)})
    MERGE (p)-[:DIRECTED]-&amp;gt;(m))
FOREACH (actor in split(row.actors, &amp;#x27;|&amp;#x27;) | 
    MERGE (p:Person {name:trim(actor)})
    MERGE (p)-[:ACTED_IN]-&amp;gt;(m))
FOREACH (genre in split(row.genres, &amp;#x27;|&amp;#x27;) | 
    MERGE (g:Genre {name:trim(genre)})
    MERGE (m)-[:IN_GENRE]-&amp;gt;(g))
&amp;quot;&amp;quot;&amp;quot;
#用Loadcsv 在线下载并构建电影知识图谱数据

graph.query(movies_query)
graph.refresh_schema() #刷新schema


chain = GraphCypherQAChain.from_llm(graph=graph,allow_dangerous_requests=True,llm=llm, verbose=True)
response = chain.invoke({&amp;quot;query&amp;quot;: &amp;quot;电影《Casino》的演员阵容是怎样的？&amp;quot;}) #提问
print(response) #回答
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;回答如下：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-shell&quot;&gt;&lt;code&gt;[1m&amp;gt; Entering new GraphCypherQAChain chain...[0m
Generated Cypher:
[32;1m[1;3mMATCH (p:Person)-[:ACTED_IN]-&amp;gt;(m:Movie {title: &amp;#x27;Casino&amp;#x27;}) RETURN p.name[0m
Full Context:
[32;1m[1;3m[{&amp;#x27;p.name&amp;#x27;: &amp;#x27;James Woods&amp;#x27;}, {&amp;#x27;p.name&amp;#x27;: &amp;#x27;Joe Pesci&amp;#x27;}, {&amp;#x27;p.name&amp;#x27;: &amp;#x27;Robert De Niro&amp;#x27;}, {&amp;#x27;p.name&amp;#x27;: &amp;#x27;Sharon Stone&amp;#x27;}][0m

[1m&amp;gt; Finished chain.[0m
{&amp;#x27;query&amp;#x27;: &amp;#x27;电影《Casino》的演员阵容是怎样的？&amp;#x27;, &amp;#x27;result&amp;#x27;: &amp;#x27;电影《Casino》的演员阵容包括詹姆斯·伍兹（James Woods）、乔·佩西（Joe Pesci）、罗伯特·德尼罗（Robert De Niro）和莎朗·斯通（Sharon Stone）。&amp;#x27;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 26 May 2025 01:46:57 GMT</pubDate></item><item><title>Neo4j官方教程：第22节，数据建模设计</title><link>http://neo4j.com.cn/topic/682700deb13f67342db8ad69</link><guid>http://neo4j.com.cn/topic/682700deb13f67342db8ad69</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/modeling-designs/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/modeling-designs/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;数据建模设计&lt;/h3&gt;
&lt;p&gt;在本节中，您将学习如何使用各种建模决策来表示图数据。数据模型的构建方式会影响查询和性能。我们的目标是教您如何评估模型并进行适当的更改，以便为您的用例定义最佳解决方案并最大化查询性能。&lt;/p&gt;
&lt;h3&gt;为什么数据模型很重要&lt;/h3&gt;
&lt;p&gt;与任何数据库一样，您设计的数据模型对确定查询逻辑和数据存储结构都很重要。这种实践也适用于图数据库，但有一个例外：Neo4j 是无模式的，这意味着您的数据模型可以随业务需求轻松调整和变化。&lt;/p&gt;
&lt;h4&gt;常见场景&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;需要收集新字段并进行新分析？&lt;/li&gt;
&lt;li&gt;需要改变对客户或其他实体的解释方式并修改其定义？&lt;/li&gt;
&lt;li&gt;法规要求系统减少信息采集或限制可读性（更改数据格式/类型）？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;您可能在一家公司工作过，其中每个区域或部门对领域的定义都不同。以通用客户域为例：对于业务内的不同区域，客户可以被定义为不同类型的个体。这些定义也可能随时间变化，或者公司可能决定统一各部门之间客户的含义。&lt;/p&gt;
&lt;h3&gt;Neo4j的优势&lt;/h3&gt;
&lt;p&gt;如果您使用过其他类型的数据库，您会熟悉这些场景所涉及的开发和管理工作。然而，Neo4j允许您轻松地对图的局部或整体进行详细和广泛的更改：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持随时间推移的小规模更改&lt;/li&gt;
&lt;li&gt;支持包含实体多种所需信息的广泛定义&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;开发人员和架构师只需要确定：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据模型的结构&lt;/li&gt;
&lt;li&gt;如何定义用于查询的实体&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;属性与关系的对比&lt;/h3&gt;
&lt;p&gt;在早期设计决策中，您可能会遇到是将某些内容建模为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点上的属性&lt;/li&gt;
&lt;li&gt;还是与独立节点的关系&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，可以将电影类型作为 Movie 节点上的属性进行建模。&lt;/p&gt;
&lt;p&gt;这种设计选择将影响：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询的编写方式&lt;/li&gt;
&lt;li&gt;遍历图数据的性能&lt;/li&gt;
&lt;li&gt;数据的维护和扩展性&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在接下来的内容中，我们将介绍查看不同数据集的几种方法，并展示每种方法如何影响图数据的查询和遍历性能。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/modeling_genre_property-arr.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;编写查询来查找特定电影的类型是很简单的。只需找到想要了解的 Movie 节点，然后返回 genre 属性中列出的值。但是，要找出共享类型的电影，需要一个更复杂的查询来：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;查找每个 Movie 节点&lt;/li&gt;
&lt;li&gt;遍历每个电影的类型属性数组&lt;/li&gt;
&lt;li&gt;与第二部电影的类型属性数组中的每个值进行比较&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这会影响性能（嵌套循环和节点属性比较），查询也会更加复杂。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;查找特定电影的类型
MATCH (m:Movie {title:&amp;quot;The Matrix&amp;quot;})
RETURN m.genre;

&amp;#x2F;&amp;#x2F;查找共享类型的电影
MATCH (m1:Movie), (m2:Movie)
WHERE any(x IN m1.genre WHERE x IN m2.genre)
AND m1 &amp;lt;&amp;gt; m2
RETURN m1, m2;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在，相反，如果您将电影及其类型建模为单独的节点，并在它们之间创建一种关系，您将得到如图2所示的模型。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/modeling_genre_node-arr.svg&quot; alt=&quot;image&quot;&gt;
这将为流派创建一个完全独立的实体(节点)，允许您将所有具有共享流派的电影连接到该流派节点。让我们看看这如何改变我们的查询。为了找到特定电影的流派，它首先需要找到它正在寻找的电影节点(在本例中为“矩阵”)，然后找到通过IN_GENRE关系连接到该电影的节点。&lt;/p&gt;
&lt;p&gt;最大的区别在于第二个查询的语法，该查询用于查找哪些电影具有相同的类型。它比我们早期的版本简单得多，因为它使用自然的图形模式(实体-关系-实体)来查找所需的信息。首先，Cypher找到一部电影及其相关的类型，然后寻找同一类型的第二部电影。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;find the genres for a particular movie
MATCH (m:Movie {title:&amp;quot;The Matrix&amp;quot;}),
      (m)-[:IN_GENRE]-&amp;gt;(g:Genre)
RETURN g.name;

&amp;#x2F;&amp;#x2F;find which movies share genres
MATCH (m1:Movie)-[:IN_GENRE]-&amp;gt;(g:Genre),
      (m2:Movie)-[:IN_GENRE]-&amp;gt;(g)
RETURN m1, m2, g
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;数据模型的版本没有好坏之分，但是“最佳”选项很大程度上取决于您打算对数据运行的查询类型。&lt;/p&gt;
&lt;p&gt;如果您计划对单个项目进行分析，并且只返回关于该实体的详细信息(比如特定电影的类型)，那么第一个数据模型将非常适合您的需求。但是，如果您需要运行分析来寻找实体之间的共同点或者查看一组节点，那么第二个数据模型肯定会提高这些类型的查询的性能。&lt;/p&gt;
&lt;h3&gt;复杂数据结构&lt;/h3&gt;
&lt;p&gt;众所周知，不是所有的数据模型都简单直接。数据是混乱的，模型必须尝试更好地组织它以帮助我们看到模式并做出决策。&lt;/p&gt;
&lt;p&gt;漫威漫画数据是一个难以建模的复杂数据结构的典型例子。在漫威宇宙中，漫画中有角色出场或担任主角。漫画可以按特定时间的故事线或叙事组织成系列，重大事件可能发生在定义角色路径或系列的漫画中。创作者（包括作家、插画师等）是漫画的作者，定义故事线、角色改编和发生的事件。多个创作者也可以互换参与创作漫画或系列。&lt;/p&gt;
&lt;p&gt;这个数据集已经看起来很复杂，有多个实体和关系在起作用。在尝试对这里存在的层次结构和中间实体进行建模时，又增加了一层复杂性。&lt;/p&gt;
&lt;p&gt;如果您有时间，可以在 Vimeo 上观看 Peter 演讲的完整视频链接，但我们想强调 Peter 在数据集中讨论的两个关键挑战。&lt;/p&gt;
&lt;p&gt;首先，他发现漫画角色往往极其动态。许多角色无法通过名字、服装或任何特定属性来识别，因为这些都经常变化。&lt;/p&gt;
&lt;p&gt;其次，Peter 发现了时序问题。对于漫画宇宙的新手来说，有些人可能想确定从哪里开始或接下来看哪些漫画。然而，漫画期刊并不总是按顺序编号的，甚至有些故事情节会跨越多个系列来回出现。这使得分离某些故事块或事件以及角色的演绎变得极其困难。&lt;/p&gt;
&lt;h3&gt;示例：中间节点&lt;/h3&gt;
&lt;p&gt;在这个模型中有用的一种建模技术是超边的概念。超边通常用于建模存在于两个以上实体之间的关系。Neo4j 不支持两个以上节点之间的关系，而是使用中间节点来建模这种关系。它们通常用于表示多个实体在某个时间点的连接。&lt;/p&gt;
&lt;p&gt;这方面的一个常见例子是大学课程。同一门课程可能有多个开设班次，使用相同的教师在相同的建筑物中等。课程的每个部分（或开设班次）就成为课程的一个实例。&lt;/p&gt;
&lt;p&gt;Marvel 的 Peter 处理他们数据中的中间节点的方式是创建一个 Appearance 节点，该节点表示特定时间点上 Person 和 Alias 的交集。这个 Appearance 可以关联到多个 Moment 节点，在这些节点中人物和化身作为一个整体出现。这在下面的模型中表示（也在视频中）。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/modeling_marvel_hyperedge_appearance-arr.svg&quot; alt=&quot;image&quot;&gt;
在关系型存储中，试图对所有这些复杂方面进行分类和关联将极其困难，并进一步使整体数据的分析和审查变得复杂。图模型允许他们对这个高度动态的宇宙进行建模，并跟踪其数据中所有不断变化的连接。对于这个用例，图是完美的选择。&lt;/p&gt;
&lt;h3&gt;时间绑定数据和版本控制&lt;/h3&gt;
&lt;p&gt;建模时间特定数据和关系的一种方式是在关系类型中包含数据。由于 Neo4j 专门针对实体之间的关系遍历进行了优化，因此您通常可以通过将日期指定为关系类型并仅遍历特定日期的关系来提高查询性能。&lt;/p&gt;
&lt;p&gt;一个常见的例子是对航空公司航班进行建模。航空公司在特定日期有从特定地点到特定地点的航班。我们可以从下面的图 4 所示的模型开始，展示航班如何在机场之间运行。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/modeling_airport_flights-arr.svg&quot; alt=&quot;image&quot;&gt;
我们很快就会意识到，我们需要对存在于两个目的地之间的飞行实体进行建模，因为多架飞机可以在一天内多次往返于两个目的地之间。&lt;/p&gt;
&lt;p&gt;然而，您的查询可能仍然显示了该模型在过滤特定机场的所有航班方面的弱点——特别是对于伦敦和其他主要城市，这些城市在任何时间跨度内都有数百个航班连接到某个机场节点。检查每个航班节点的几个属性在资源上可能是昂贵的。&lt;/p&gt;
&lt;p&gt;如果我们要为特定的机场日创建一个节点，并在类型中创建一个带有日期的关系，那么我们可以编写查询来查找任何指定日期(或日期范围)从机场起飞的航班。这样，您就不需要检查每个航班与机场的关系。相反，你只会关注那些你在乎的日期的关系。这个模型结果如下图所示。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/modeling_airport_flight_dates-arr.svg&quot; alt=&quot;image&quot;&gt;
版本控制类似于上面的模型，我们创建了一个日期关系类型，我们也可以用它来跟踪数据的版本。跟踪数据结构的变化或显示当前和过去的值对于审计、趋势分析等非常重要。&lt;/p&gt;
&lt;p&gt;例如，如果您想在一个人和他的当前地址之间创建一个新的有生效日期的关系，但是还想保留过去的地址，那么您可以使用相同的原则在关系类型中包含一个日期。为了找到这个人的当前地址，查询将查找最近的关系。&lt;/p&gt;
&lt;p&gt;有时，您可能会发现一个模型对于您需要的一个场景确实很好，但是另一个模型对于其他场景更好。例如，一些模型可以更好地处理写查询，而另一些模型可以更好地处理读查询。这两种能力对您的用例都很重要，那么您会怎么做呢？&lt;/p&gt;
&lt;p&gt;在这些情况下，您可以将这两种模式结合起来，利用各自的优势。是的，您可以在您的图表中使用多个数据模型！&lt;/p&gt;
&lt;p&gt;代价是现在您需要维护两个模型。每当您创建一个新的节点或关系，或者更新图的一部分时，您都需要进行更改以适应这两种模型。这也会影响查询性能，因为更新每个模型可能需要两倍的语法。&lt;/p&gt;
&lt;p&gt;虽然这肯定是一个可能的选择，但是您应该知道维护成本，并评估这些成本是否能够被您将看到的每个所需查询的性能改进所抵消。如果是这样，能够使用多个数据模型是一个很好的解决方案！&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 16 May 2025 09:09:50 GMT</pubDate></item><item><title>Neo4j官方教程：第21节，重构图数据模型</title><link>http://neo4j.com.cn/topic/6826fa35b13f67342db8ad68</link><guid>http://neo4j.com.cn/topic/6826fa35b13f67342db8ad68</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/tutorial-refactoring/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/tutorial-refactoring/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;教程：重构图数据模型&lt;/h3&gt;
&lt;p&gt;重构是更改数据模型和图的过程。需要重构数据模型的主要原因包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前建模的图无法覆盖所有用例&lt;/li&gt;
&lt;li&gt;出现了新的用例&lt;/li&gt;
&lt;li&gt;用例的 Cypher® 查询在图扩展时性能不佳&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了满足这些需求，本教程将指导您设计、实现和测试一个经过重构的数据模型，并更新 Cypher 查询。&lt;/p&gt;
&lt;h3&gt;前置条件&lt;/h3&gt;
&lt;p&gt;本教程是《教程：创建图数据模型》的后续内容。在继续之前，您需要完成该教程中创建的数据模型。&lt;/p&gt;
&lt;p&gt;或者，您也可以现在从头开始创建。选择您喜欢的部署方法，并使用以下代码添加数据：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (Apollo13:Movie {title: &amp;#x27;Apollo 13&amp;#x27;, tmdbID: 568, released: &amp;#x27;1995-06-30&amp;#x27;, imdbRating: 7.6, genres: [&amp;#x27;Drama&amp;#x27;, &amp;#x27;Adventure&amp;#x27;, &amp;#x27;IMAX&amp;#x27;]})
CREATE (TomH:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, tmdbID: 31, born: &amp;#x27;1956-07-09&amp;#x27;})
CREATE (MegR:Person {name: &amp;#x27;Meg Ryan&amp;#x27;, tmdbID: 5344, born: &amp;#x27;1961-11-19&amp;#x27;})
CREATE (DannyD:Person {name: &amp;#x27;Danny DeVito&amp;#x27;, tmdbID: 518, born: &amp;#x27;1944-11-17&amp;#x27;})
CREATE (JackN:Person {name: &amp;#x27;Jack Nicholson&amp;#x27;, tmdbID: 514, born: &amp;#x27;1937-04-22&amp;#x27;})
CREATE (SleeplessInSeattle:Movie {title: &amp;#x27;Sleepless in Seattle&amp;#x27;, tmdbID: 858, released: &amp;#x27;1993-06-25&amp;#x27;, imdbRating: 6.8, genres: [&amp;#x27;Comedy&amp;#x27;, &amp;#x27;Drama&amp;#x27;, &amp;#x27;Romance&amp;#x27;]})
CREATE (Hoffa:Movie {title: &amp;#x27;Hoffa&amp;#x27;, tmdbID: 10410, released: &amp;#x27;1992-12-25&amp;#x27;, imdbRating: 6.6, genres: [&amp;#x27;Crime&amp;#x27;, &amp;#x27;Drama&amp;#x27;]})

MERGE (TomH)-[:ACTED_IN {roles:&amp;#x27;Jim Lovell&amp;#x27;}]-&amp;gt;(Apollo13)
MERGE (TomH)-[:ACTED_IN {roles:&amp;#x27;Sam Baldwin&amp;#x27;}]-&amp;gt;(SleeplessInSeattle)
MERGE (MegR)-[:ACTED_IN {roles:&amp;#x27;Annie Reed&amp;#x27;}]-&amp;gt;(SleeplessInSeattle)
MERGE (DannyD)-[:DIRECTED]-&amp;gt;(Hoffa)
MERGE (DannyD)-[:ACTED_IN {roles:&amp;#x27;Robert &amp;quot;Bobby&amp;quot; Ciaro&amp;#x27;}]-&amp;gt;(Hoffa)
MERGE (JackN)-[:ACTED_IN {roles:&amp;#x27;Hoffa&amp;#x27;}]-&amp;gt;(Hoffa)

CREATE (Sandy:User {name: &amp;#x27;Sandy Jones&amp;#x27;, userID: 1})
CREATE (Clinton:User {name: &amp;#x27;Clinton Spencer&amp;#x27;, userID: 2})

MERGE (Sandy)-[:RATED {rating:5}]-&amp;gt;(Apollo13)
MERGE (Sandy)-[:RATED {rating:4}]-&amp;gt;(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(Apollo13)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(Hoffa)
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;剩余或新用例&lt;/h3&gt;
&lt;p&gt;假设您想知道有哪些电影可以用某种语言观看。&lt;/p&gt;
&lt;p&gt;要回答这个问题，您需要先将此信息添加到图中。然而，添加新数据会带来重复的风险，进而影响图的性能。&lt;/p&gt;
&lt;p&gt;为演示这种情况，向 ‘Movie’ 节点添加新的 languages 属性及其对应值：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (Apollo13:Movie {title:&amp;#x27;Apollo 13&amp;#x27;})
MATCH (SleeplessInSeattle:Movie {title:&amp;#x27;Sleepless in Seattle&amp;#x27;})
MATCH (Hoffa:Movie {title:&amp;#x27;Hoffa&amp;#x27;})
SET Apollo13.languages = [&amp;#x27;English&amp;#x27;]
SET SleeplessInSeattle.languages = [&amp;#x27;English&amp;#x27;]
SET Hoffa.languages = [&amp;#x27;English&amp;#x27;, &amp;#x27;Italian&amp;#x27;, &amp;#x27;Latin&amp;#x27;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/movie-languages.svg&quot; alt=&quot;image&quot;&gt;
要检索所有英语电影，执行此查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WHERE &amp;#x27;English&amp;#x27; IN m.languages
RETURN m.title
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果将返回电影 “Apollo 13”、“Sleepless in Seattle” 和 “Hoffa”。&lt;/p&gt;
&lt;p&gt;此查询检索所有 Movie 节点然后测试 languages 属性是否包含值 English。这种方法没错，但随着图的扩展可能遇到两个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;查询必须检索所有 Movie 节点 → 随着图的扩展，这种建模方式会降低查询性能&lt;/li&gt;
&lt;li&gt;language 属性值在多个 Movie 节点中重复 → 如果多个节点共享相同的属性值，说明该属性值可以作为新实体（如节点或关系）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;解决方案是将 languages 属性重构为节点，并用新关系将其连接到 Movie 节点。
现在：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/language-before.svg&quot; alt=&quot;image&quot;&gt;
重构：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/language-after.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;消除重复数据&lt;/h3&gt;
&lt;p&gt;要将节点属性 languages 重构为节点，可以使用以下查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WITH m, m.languages AS languages
UNWIND languages AS language
MERGE (l:Language {name: language})
MERGE (m)-[:IN_LANGUAGE]-&amp;gt;(l)
REMOVE m.languages
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询分解说明：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UNWIND Movie 节点的 languages 属性，将其条目转换为新的 Language 节点&lt;/li&gt;
&lt;li&gt;创建 IN_LANGUAGE 关系连接 Movie 节点与其对应的 Language 节点&lt;/li&gt;
&lt;li&gt;移除 Movie 节点的 languages 属性
如图：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/language-nodes.svg&quot; alt=&quot;image&quot;&gt;
重构后，图中应只有一个值为 “English” 的 Language 节点，相关电影与其相连。这消除了大量重复并提高了图扩展时的性能。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;处理复杂数据&lt;/h3&gt;
&lt;p&gt;假设出现了需要每部电影制片公司信息的新用例。制片公司数据包括物理地址，这可以视为复杂数据。&lt;/p&gt;
&lt;p&gt;可以通过创建 ProductionCompany 节点和地址属性将此信息添加到图中：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (p:ProductionCompany {name:&amp;#x27;Imagine Entertainment&amp;#x27;, country:&amp;#x27;US&amp;#x27;, postalCode:90212, state:&amp;#x27;CA&amp;#x27;, city:&amp;#x27;Beverly Hills&amp;#x27;, address1:&amp;#x27;10351 Santa Monica Blvd&amp;#x27;})
MERGE (Apollo13:Movie {title:&amp;#x27;Apollo 13&amp;#x27;})
CREATE (p)-[:PRODUCED]-&amp;gt;(Apollo13)
CREATE (jerseyFilms:ProductionCompany {name:&amp;#x27;Jersey Films&amp;#x27;, country:&amp;#x27;US&amp;#x27;, postalCode:90049, state:&amp;#x27;CA&amp;#x27;, city:&amp;#x27;Los Angeles&amp;#x27;, address1:&amp;#x27;10351 Santa Monica Blvd&amp;#x27;})
MERGE (hoffa:Movie {title:&amp;#x27;Hoffa&amp;#x27;})
CREATE (jerseyFilms)-[:PRODUCED]-&amp;gt;(hoffa)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/producers.svg&quot; alt=&quot;image&quot;&gt;
在节点上存储复杂数据的问题
以这种方式在节点上存储复杂数据可能存在以下问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据重复
多个制片公司可能位于相同位置，导致信息在多个节点上重复
示例：之前我们将’languages’属性重构为节点，就是为了避免&amp;quot;English&amp;quot;在所有 Movie 节点上重复&lt;/li&gt;
&lt;li&gt;过度获取
查询节点信息时需要不必要地检索更多同类节点
示例：要查找位于加利福尼亚的制片公司时，需要扫描所有 ProductionCompany 节点的属性来获取 state 值。而如果将加利福尼亚作为独立节点，就能提供更短的访问路径，避免获取多余信息
替代方案：可以创建索引&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;数据建模目标&lt;/h4&gt;
&lt;p&gt;数据建模的核心目标是减少查询时需要访问的图数据量。如果出现以下情况，需要考虑重构模型：&lt;/p&gt;
&lt;p&gt;图中包含大量重复数据
查询仍在过度获取数据
当前模型分析
目前模型中新增了 ProductionCompany 节点标签，包含多个地址属性。这些属性值存在大量重复，不够理想。为提高效率，应：&lt;/p&gt;
&lt;p&gt;检查重复的键值
考虑将其转换为新实体（节点或关系）
重构示例
由于两家制片公司都在加利福尼亚，可以：&lt;/p&gt;
&lt;p&gt;将州属性转换为 State 节点
通过新的 LOCATED_AT 关系连接制片公司
移除制片公司节点上的 state 属性
重构效果
按州查询制片公司时可直接基于 &lt;a href=&quot;http://State.name&quot;&gt;State.name&lt;/a&gt; 值过滤
避免评估所有 ProductionCompany 节点的 state 属性
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/california.svg&quot; alt=&quot;image&quot;&gt;
总结
处理复杂数据的重构方式取决于：&lt;/p&gt;
&lt;p&gt;需要解答的问题
图扩展时查询的性能表现
下一步是通过测试来衡量图中的性能表现。&lt;/p&gt;
&lt;h3&gt;使用特定关系&lt;/h3&gt;
&lt;p&gt;当项目有需要经常检索某些信息的重复用例时，可以使用特定关系作为重构策略。好处包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;减少需要检索的节点数量&lt;/li&gt;
&lt;li&gt;提高查询性能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，如果经常需要检索 1995 年的演员信息，查询可以从：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE p.name = &amp;#x27;Tom Hanks&amp;#x27; AND m.released STARTS WITH &amp;#x27;1995&amp;#x27;
RETURN DISTINCT m.title AS Movie
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;优化为：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN_1995]-(m:Movie)
WHERE p.name = &amp;#x27;Tom Hanks&amp;#x27;
RETURN m.title AS Movie
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;重新测试图&lt;/h3&gt;
&lt;h3&gt;重新测试图的用例查询&lt;/h3&gt;
&lt;p&gt;以下是需要重新检查的用例查询列表：&lt;/p&gt;
&lt;h4&gt;1. 哪些人参演了某部电影？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-&amp;gt;(m:Movie {title:&amp;#x27;Hoffa&amp;#x27;})
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;2. 谁导演了某部电影？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:DIRECTED]-&amp;gt;(m:Movie {title:&amp;#x27;Hoffa&amp;#x27;})
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;3. 某人参演了哪些电影？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name:&amp;#x27;Tom Hanks&amp;#x27;})-[:ACTED_IN]-&amp;gt;(m:Movie)
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;4. 有多少用户为某部电影评分？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie {title: &amp;#x27;Apollo 13&amp;#x27;})
RETURN COUNT {(:User)-[:RATED]-&amp;gt;(m)} AS &amp;#96;Number of reviewers&amp;#96;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;5. 谁是某部电影中最年轻的演员？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE m.title = &amp;#x27;Hoffa&amp;#x27;
RETURN p.name AS Actor, p.born as &amp;#96;Year Born&amp;#96; 
ORDER BY p.born DESC LIMIT 1
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;6. 某人在电影中扮演什么角色？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name:&amp;#x27;Tom Hanks&amp;#x27;})-[a:ACTED_IN]-&amp;gt;(m:Movie {title: &amp;#x27;Apollo 13&amp;#x27;})
RETURN a.roles
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;7. 某年按 IMDB 评分最高的电影是哪部？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WHERE m.released STARTS WITH &amp;#x27;1995&amp;#x27;
RETURN m.title as Movie, m.imdbRating as Rating 
ORDER BY m.imdbRating DESC LIMIT 1
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;8. 某演员参演了哪些剧情片？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE p.name = &amp;#x27;Tom Hanks&amp;#x27; AND
&amp;#x27;Drama&amp;#x27; IN m.genres
RETURN m.title AS Movie
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;9. 哪些用户给某部电影打了5分？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (u:User)-[r:RATED]-(m:Movie)
WHERE m.title = &amp;#x27;Apollo 13&amp;#x27; AND
r.rating = 5
RETURN u.name as Reviewer
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;10. 哪些电影是英语电影？&lt;/h4&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WHERE m.languages = &amp;#x27;English&amp;#x27;
RETURN m.title as Movie in English
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;说明&lt;/h3&gt;
&lt;p&gt;需要检查以上每个查询，看是否可以利用重构后的数据模型进行优化。比如最后一个查询&amp;quot;哪些电影是英语电影？“就可以使用新的 Language 节点和 IN_LANGUAGE 关系进行重写。
重构后，应重新检查所有用例查询。例如用例&amp;quot;哪些电影是英语的？”：&lt;/p&gt;
&lt;p&gt;重构前：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WHERE m.languages = &amp;#x27;English&amp;#x27;
RETURN m.title as Movie in English
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;重构后：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)-[:IN_LANGUAGE]-&amp;gt;(l:Language)
WHERE l.name = &amp;#x27;English&amp;#x27;
RETURN m.title as Movie in English
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;性能检查&lt;/h3&gt;
&lt;p&gt;在实际应用中，特别是图完全扩展时，可以通过 PROFILE 检查新查询的性能改进：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;PROFILE MATCH (n:Person)
RETURN n
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/query-plan.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;持续学习&lt;/h3&gt;
&lt;p&gt;大多数重构工作是为了重新利用或添加更多信息到图中。&lt;/p&gt;
&lt;p&gt;可以在 GraphAcademy 的 Graph Data Modeling Fundamentals 交互式课程中学习更多重构策略，如将 Person 节点拆分为 Actor 和 Director 节点、将 Movie 节点的 genre 属性转换为节点等。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 16 May 2025 08:41:25 GMT</pubDate></item><item><title>Neo4j官方教程：第20节，创建图数据模型</title><link>http://neo4j.com.cn/topic/680df39fb13f67342db8ad62</link><guid>http://neo4j.com.cn/topic/680df39fb13f67342db8ad62</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling/tutorial-data-modeling/&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling/tutorial-data-modeling/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;教程：创建图数据模型&lt;/h1&gt;
&lt;p&gt;本教程旨在帮助您根据预期用途对数据进行建模。您将使用电影示例数据集作为主要资源。&lt;/p&gt;
&lt;p&gt;有关数据建模基础的交互式课程，请参阅 &lt;a href=&quot;https://neo4j.com/graphacademy/&quot;&gt;GraphAcademy&lt;/a&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;定义领域&lt;/h2&gt;
&lt;p&gt;在本教程中，您将使用电影示例数据集。领域包括电影、出演或导演电影的人，以及对电影进行评分的用户。通过这些实体之间的连接（关系），您可以发现领域中的洞察。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;定义用例&lt;/h2&gt;
&lt;p&gt;在定义领域后，您需要确定应用程序的用例。换句话说，您需要回答哪些问题？&lt;/p&gt;
&lt;p&gt;您可以列出问题来帮助确定应用程序的用例。这些问题将帮助您定义应用程序的需求以及图中必须包含的数据。&lt;/p&gt;
&lt;p&gt;在本教程中，您的应用程序应能够回答以下问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些人出演了一部电影？&lt;/li&gt;
&lt;li&gt;哪个人导演了一部电影？&lt;/li&gt;
&lt;li&gt;某人出演了哪些电影？&lt;/li&gt;
&lt;li&gt;有多少用户对一部电影进行了评分？&lt;/li&gt;
&lt;li&gt;谁是出演电影的最年轻的人？&lt;/li&gt;
&lt;li&gt;某人在电影中扮演了什么角色？&lt;/li&gt;
&lt;li&gt;根据 IMDb，某一年评分最高的电影是哪部？&lt;/li&gt;
&lt;li&gt;某演员出演了哪些剧情片？&lt;/li&gt;
&lt;li&gt;哪些用户给某部电影打了 5 分？&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;定义目的&lt;/h2&gt;
&lt;p&gt;在为应用程序设计图数据模型时，您可能需要数据模型和实例模型。&lt;/p&gt;
&lt;h3&gt;数据模型&lt;/h3&gt;
&lt;p&gt;数据模型描述了领域中的节点和关系，包括标签、类型和属性。它不包含任何数据，但显示了回答用例所需的信息。&lt;/p&gt;
&lt;p&gt;在此阶段，您可以选择使用无代码工具来可视化您的计划。例如，使用 &lt;a href=&quot;https://arrows.app/&quot;&gt;Arrows.app&lt;/a&gt;，您可以绘制包含节点标签、关系类型和属性的数据模型：&lt;/p&gt;
&lt;p&gt;示例数据模型包括表示人和电影的两个节点，通过两种关系连接。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/sample-data-model.svg&quot; alt=&quot;image&quot;&gt;
根据示例领域和初始问题，您可以列出初始模型中需要的信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;区分出演电影、导演电影和评分电影的人。&lt;/li&gt;
&lt;li&gt;评分的内容、数量以及提交时间。&lt;/li&gt;
&lt;li&gt;演员在电影中扮演的角色及其年龄。&lt;/li&gt;
&lt;li&gt;电影的类型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意，在模型中，标签、关系类型和属性键遵循特定语法。在 Cypher® 中，这些称为标识符，区分大小写，字符串值也区分大小写。&lt;/p&gt;
&lt;p&gt;推荐的命名规范：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;标签&lt;/strong&gt;：首字母大写，使用驼峰命名法（例如：&lt;code&gt;Person&lt;/code&gt;、&lt;code&gt;Movie&lt;/code&gt;、&lt;code&gt;ImdbUser&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关系类型&lt;/strong&gt;：全大写，使用下划线分隔（例如：&lt;code&gt;DIRECTED&lt;/code&gt;、&lt;code&gt;ACTED_IN&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;属性键&lt;/strong&gt;：不大写，使用驼峰命名法（例如：&lt;code&gt;name&lt;/code&gt;、&lt;code&gt;userID&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在创建初始模型时，专注于模型的高层设计，即实体如何连接。更详细的分配信息将在“定义实体”步骤中描述。&lt;/p&gt;
&lt;h3&gt;实例模型&lt;/h3&gt;
&lt;p&gt;实例模型是存储和处理实际数据的表示。您可以使用实例模型测试用例。&lt;/p&gt;
&lt;p&gt;要创建实例模型，您需要一些示例数据并将其加载到所选的部署中。以下是一个小型但具有代表性的数据集：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/instance-example.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (Apollo13:Movie {title: &amp;#x27;Apollo 13&amp;#x27;, tmdbID: 568, released: &amp;#x27;1995-06-30&amp;#x27;, imdbRating: 7.6, genres: [&amp;#x27;Drama&amp;#x27;, &amp;#x27;Adventure&amp;#x27;, &amp;#x27;IMAX&amp;#x27;]})
CREATE (TomH:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, tmdbID: 31, born: &amp;#x27;1956-07-09&amp;#x27;})
CREATE (MegR:Person {name: &amp;#x27;Meg Ryan&amp;#x27;, tmdbID: 5344, born: &amp;#x27;1961-11-19&amp;#x27;})
CREATE (DannyD:Person {name: &amp;#x27;Danny DeVito&amp;#x27;, tmdbID: 518, born: &amp;#x27;1944-11-17&amp;#x27;})
CREATE (JackN:Person {name: &amp;#x27;Jack Nicholson&amp;#x27;, tmdbID: 514, born: &amp;#x27;1937-04-22&amp;#x27;})
CREATE (SleeplessInSeattle:Movie {title: &amp;#x27;Sleepless in Seattle&amp;#x27;, tmdbID: 858, released: &amp;#x27;1993-06-25&amp;#x27;, imdbRating: 6.8, genres: [&amp;#x27;Comedy&amp;#x27;, &amp;#x27;Drama&amp;#x27;, &amp;#x27;Romance&amp;#x27;]})
CREATE (Hoffa:Movie {title: &amp;#x27;Hoffa&amp;#x27;, tmdbID: 10410, released: &amp;#x27;1992-12-25&amp;#x27;, imdbRating: 6.6, genres: [&amp;#x27;Crime&amp;#x27;, &amp;#x27;Drama&amp;#x27;]})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;建议手动使用 Cypher 添加数据以练习数据建模。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;定义实体&lt;/h2&gt;
&lt;p&gt;实例模型帮助您预览数据将如何存储为节点、关系和属性。下一步是通过更多细节完善模型。&lt;/p&gt;
&lt;h3&gt;标签&lt;/h3&gt;
&lt;p&gt;应用程序用例中的主要名词在模型中表示为节点，并可用作节点标签。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些人出演了一部电影？&lt;/li&gt;
&lt;li&gt;有多少用户对一部电影进行了评分？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;初始模型中的节点为 &lt;code&gt;Person&lt;/code&gt;、&lt;code&gt;Movie&lt;/code&gt; 和 &lt;code&gt;User&lt;/code&gt;。请注意，创建模型是一个迭代过程，经过重构后，模型可能会有所不同。&lt;/p&gt;
&lt;h3&gt;节点属性&lt;/h3&gt;
&lt;p&gt;您可以使用节点属性来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定位查询的起点&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})-[:ACTED_IN]-(m:Movie)
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;遍历图&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-(m:Movie {title: &amp;#x27;Apollo 13&amp;#x27;})-[:RATED]-(u:User)
RETURN p, u
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;返回查询数据&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})-[:ACTED_IN]-(m:Movie)
RETURN m.title, m.released
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下是一些示例用例及其查询：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;用例&lt;/th&gt;
&lt;th&gt;步骤&lt;/th&gt;
&lt;th&gt;查询示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;哪些人出演了一部电影？&lt;/td&gt;
&lt;td&gt;检索电影标题，返回演员姓名。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (m:Movie {title:&apos;Hoffa&apos;})&amp;lt;-[r:ACTED_IN]-(p:Person) RETURN p.name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;哪个人导演了一部电影？&lt;/td&gt;
&lt;td&gt;检索电影标题，返回导演姓名。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (m:Movie {title:&apos;Hoffa&apos;})&amp;lt;-[r:DIRECTED]-(p:Person) RETURN p.name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;某人出演了哪些电影？&lt;/td&gt;
&lt;td&gt;检索演员姓名，返回电影标题。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (p:Person {name:&apos;Tom Hanks&apos;})-[:ACTED_IN]-&amp;gt;(m:Movie) RETURN m.title&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;谁是出演电影的最年轻的人？&lt;/td&gt;
&lt;td&gt;检索电影标题，评估演员年龄，返回最年轻演员姓名。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (m:Movie {title:&apos;Sleepless in Seattle&apos;})&amp;lt;-[r:ACTED_IN]-(p:Person) RETURN p.name, p.born ORDER BY p.born ASC LIMIT 1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;某一年 IMDb 评分最高的电影是哪部？&lt;/td&gt;
&lt;td&gt;检索某年发布的所有电影，评估 IMDb 评分，返回评分最高的电影标题。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (m:Movie {release:date(&apos;1995&apos;)}) RETURN m.title, m.imdbRating ORDER BY m.imdbRating DESC LIMIT 1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;唯一标识符&lt;/h3&gt;
&lt;p&gt;在 Cypher 中，可以创建两个具有完全相同数据的节点。然而，从数据管理和模型角度来看，不同的节点应包含不同的数据。您可以使用唯一标识符确保每个节点都是独立且可区分的实体。&lt;/p&gt;
&lt;p&gt;例如，&lt;code&gt;Movie.tmdbID&lt;/code&gt; 是一个很好的唯一标识符，因为数据库中可能有不同的电影具有相同的标题，但 &lt;code&gt;tmdbID&lt;/code&gt; 属性将不同，从而充当唯一标识符。&lt;/p&gt;
&lt;p&gt;建议通过使用唯一性约束来强制执行唯一标识符。有关更多信息，请参阅 &lt;a href=&quot;https://neo4j.com/docs/cypher-manual/current/constraints/&quot;&gt;Cypher → 创建属性唯一性约束&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;关系&lt;/h2&gt;
&lt;p&gt;关系是节点之间的连接，这些连接是用例中的动词：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些人出演了一部电影？&lt;/li&gt;
&lt;li&gt;哪些人导演了一部电影？&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;命名&lt;/h3&gt;
&lt;p&gt;为图中的关系选择好的名称（类型）非常重要，并尽可能具体，以便 Neo4j 仅遍历相关连接。&lt;/p&gt;
&lt;p&gt;例如，与其使用通用的关系类型（如 &lt;code&gt;CONNECTED_TO&lt;/code&gt;），更倾向于使用更具体且直观的方式描述实体之间的连接。&lt;/p&gt;
&lt;p&gt;在本教程示例中，您可以定义以下关系：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ACTED_IN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DIRECTED&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;关系方向&lt;/h3&gt;
&lt;p&gt;所有关系必须有方向。在创建时，关系需要显式指定方向，或者通过模式的从左到右顺序推断方向。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relationship-direction.svg&quot; alt=&quot;image&quot;&gt;
在示例用例中，&lt;code&gt;ACTED_IN&lt;/code&gt; 关系必须从 &lt;code&gt;Person&lt;/code&gt; 节点指向 &lt;code&gt;Movie&lt;/code&gt; 节点：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (TomH)-[:ACTED_IN]-&amp;gt;(Apollo13)
MERGE (TomH)-[:ACTED_IN]-&amp;gt;(SleeplessInSeattle)
MERGE (MegR)-[:ACTED_IN]-&amp;gt;(SleeplessInSeattle)
MERGE (DannyD)-[:ACTED_IN]-&amp;gt;(Hoffa)
MERGE (DannyD)-[:DIRECTED]-&amp;gt;(Hoffa)
MERGE (JackN)-[:ACTED_IN]-&amp;gt;(Hoffa)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relationships-graph.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;关系属性&lt;/h3&gt;
&lt;p&gt;关系属性用于丰富两个节点之间的关系。当您需要知道两个节点之间的关系方式而不仅仅是它们存在关系时，可以使用关系属性进一步定义关系。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relationship-roles.svg&quot; alt=&quot;image&quot;&gt;
例如，问题“某人在电影中扮演了什么角色？”可以通过 &lt;code&gt;ACTED_IN&lt;/code&gt; 关系中的属性 &lt;code&gt;roles&lt;/code&gt; 来回答：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (TomH)-[:ACTED_IN {roles:&amp;#x27;Jim Lovell&amp;#x27;}]-&amp;gt;(Apollo13)
MERGE (TomH)-[:ACTED_IN {roles:&amp;#x27;Sam Baldwin&amp;#x27;}]-&amp;gt;(SleeplessInSeattle)
MERGE (MegR)-[:ACTED_IN {roles:&amp;#x27;Annie Reed&amp;#x27;}]-&amp;gt;(SleeplessInSeattle)
MERGE (DannyD)-[:ACTED_IN {roles:&amp;#x27;Robert &amp;quot;Bobby&amp;quot; Ciaro&amp;#x27;}]-&amp;gt;(Hoffa)
MERGE (JackN)-[:ACTED_IN {roles:&amp;#x27;Hoffa&amp;#x27;}]-&amp;gt;(Hoffa)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询示例：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name:&amp;#x27;Tom Hanks&amp;#x27;})-[r:ACTED_IN]-&amp;gt;(m:Movie {title:&amp;#x27;Apollo 13&amp;#x27;})
RETURN r.roles
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;添加更多数据&lt;/h2&gt;
&lt;p&gt;现在您已经创建了节点之间的初始连接，是时候向图中添加更多信息了。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有多少用户对一部电影进行了评分？&lt;/li&gt;
&lt;li&gt;哪些用户给某部电影打了 5 分？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为此，您需要在图中添加用户及其评分信息，这意味着数据模型的更改。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/roles-graph.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h3&gt;添加用户节点&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (Sandy:User {name: &amp;#x27;Sandy Jones&amp;#x27;, userID: 1})
MERGE (Clinton:User {name: &amp;#x27;Clinton Spencer&amp;#x27;, userID: 2})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;建议将用户信息与演员和导演分开，因为它们与电影节点的关系不同。&lt;/p&gt;
&lt;h3&gt;添加评分关系&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (Sandy)-[:RATED {rating:5}]-&amp;gt;(Apollo13)
MERGE (Sandy)-[:RATED {rating:4}]-&amp;gt;(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(Apollo13)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(SleeplessInSeattle)
MERGE (Clinton)-[:RATED {rating:3}]-&amp;gt;(Hoffa)
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/user-ratings.svg&quot; alt=&quot;image&quot;&gt;&lt;/h2&gt;
&lt;h2&gt;测试模型&lt;/h2&gt;
&lt;p&gt;在填充图以实现数据模型并使用一小组测试数据后，您现在应该测试它以确保满足每个用例。&lt;/p&gt;
&lt;p&gt;例如，测试用例“哪些人出演了一部电影？”可以运行以下查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-(m:Movie)
WHERE m.title = &amp;#x27;Sleepless in Seattle&amp;#x27;
RETURN p.name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;测试时，请确保 Cypher 语句正确。错误的查询可能导致错误地认为数据模型失败。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;重构&lt;/h2&gt;
&lt;p&gt;完成测试后，下一步是进行调整。有关说明，请参阅 &lt;a href=&quot;https://neo4j.com/docs/graph-data-modeling/current/tutorials/refactoring/&quot;&gt;教程：重构&lt;/a&gt;。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Sun, 27 Apr 2025 09:06:39 GMT</pubDate></item><item><title>Neo4j官方教程：第19节， 图数据建模是什么</title><link>http://neo4j.com.cn/topic/680b51dfb13f67342db8ad61</link><guid>http://neo4j.com.cn/topic/680b51dfb13f67342db8ad61</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/data-modeling&quot;&gt;https://neo4j.com/docs/getting-started/data-modeling&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;图数据建模是什么？&lt;/h1&gt;
&lt;p&gt;数据建模是一种定义查询逻辑和存储数据结构的实践。一个设计良好的模型是充分利用图数据库优势的关键，因为它可以提高查询性能、支持灵活查询并优化存储。&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;如何创建图数据模型&lt;/h1&gt;
&lt;p&gt;要将数据组织成数据模型，首先需要思考你想回答哪些问题。&lt;/p&gt;
&lt;p&gt;例如，假设你为一家零售公司工作，并希望了解客户购买了哪些产品。为此，你需要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;拥有关于已售产品和购买它们的客户的数据&lt;/strong&gt;：这个过程称为“实体提取”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;理解这些实体之间的关系&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;思考需要提供哪些其他细节&lt;/strong&gt;，即需要为这些实体添加哪些属性（例如客户姓名）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可选：在创建模型之前，使用无代码数据建模工具可视化模型&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如果满意，可以开始将数据写入数据库&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在这个虚构的场景中，你可以通过以下方式将信息添加到图中：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (c:Customer {name: &amp;quot;John&amp;quot;})
CREATE (p:Product {name: &amp;quot;Camera&amp;quot;})
CREATE (c)-[:BUYS]-&amp;gt;(p)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后，你可以通过查询测试这个模型（例如，John 买了什么）：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (c:Customer {name: &amp;quot;John&amp;quot;})-[b:BUYS]-&amp;gt;(p)
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请记住，图数据建模是一个迭代的过程。你的初始图数据模型只是一个起点。随着你对用例的深入了解或用例的变化，模型需要进行调整。&lt;/p&gt;
&lt;p&gt;此外，你可能会发现，尤其是在图规模扩大时，需要重构模型以确保它与业务需求保持一致。&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;总结&lt;/h1&gt;
&lt;p&gt;创建数据模型的过程包括以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;理解领域并为应用程序定义具体的用例（问题）&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通过提取实体并决定它们之间的关系，开发初始图数据模型&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;根据初始数据模型测试用例&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 Cypher® 创建包含测试数据的图&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;测试用例，包括图的性能&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;由于关键用例的变化或性能原因，重构图数据模型&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1&gt;持续学习&lt;/h1&gt;
&lt;p&gt;如果想要更深入地学习数据建模，可以尝试以下资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GraphAcademy: 数据建模基础&lt;/strong&gt;：注册一个交互式课程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;从关系型到图模型&lt;/strong&gt;：学习如何将关系型数据转换为图数据模型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据建模工具&lt;/strong&gt;：查看可用于创建数据模型的工具列表。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据建模技巧&lt;/strong&gt;：查看如何提高数据建模技能的建议。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;建模设计&lt;/strong&gt;：查看可用于项目策略的数据建模设计示例。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neo4j GraphGists&lt;/strong&gt;：查找 Neo4j 社区分享的图数据建模示例。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 25 Apr 2025 09:11:59 GMT</pubDate></item><item><title>Neo4j官方教程：第18节， Cypher 资源</title><link>http://neo4j.com.cn/topic/6800a9ffa755994623e85dc9</link><guid>http://neo4j.com.cn/topic/6800a9ffa755994623e85dc9</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/resources/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/resources/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Cypher 资源&lt;/h1&gt;
&lt;h2&gt;Cypher 基础和文档&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href&gt;GraphAcademy - Cypher 基础&lt;/a&gt; - 60分钟内学习 Cypher&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;文档: Cypher 手册&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Cypher 速查表&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Neo4j 社区站点&lt;/a&gt;: 提问和获取 Cypher 相关答案&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;面向 SQL 开发人员的 Cypher&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href&gt;视频: SQL 到 Cypher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;免费电子书: 面向 RDBMS 开发人员的图数据库&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;其他资源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href&gt;Medium博客: Cypher 优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cypher 中处理日期和时间的博客系列:
&lt;ul&gt;
&lt;li&gt;&lt;a href&gt;第1部分&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;第2部分&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;第3部分&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Mark Needham 的 Cypher 博客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Max De Marzi 的 Cypher 博客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Eve Freeman 教程: 使用 Cypher 构建 ACL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href&gt;Neo4j Medium 博客频道&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;使用 GRAPHACADEMY 学习&lt;/h2&gt;
&lt;p&gt;&lt;img src alt=&quot;badge&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Cypher 基础课程&lt;/h3&gt;
&lt;p&gt;本课程通过视频、测验和动手练习,用尽可能少的时间教您使用 Neo4j 强大的查询语言 Cypher 的基础知识。&lt;/p&gt;
&lt;p&gt;&lt;a href&gt;使用 GraphAcademy 学习 Cypher&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Thu, 17 Apr 2025 07:13:03 GMT</pubDate></item><item><title>Neo4j官方教程：第17节， 导入数据</title><link>http://neo4j.com.cn/topic/6800a7d2a755994623e85dc8</link><guid>http://neo4j.com.cn/topic/6800a7d2a755994623e85dc8</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/load-csv/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/load-csv/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;教程：导入数据&lt;/h1&gt;
&lt;p&gt;本教程演示如何使用 LOAD CSV 从 CSV 文件导入数据。&lt;/p&gt;
&lt;p&gt;通过组合 Cypher® 子句 LOAD CSV、MERGE 和 CREATE，您可以将数据导入到 Neo4j 中。LOAD CSV 允许您访问数据值并对其执行操作。&lt;/p&gt;
&lt;h2&gt;数据文件&lt;/h2&gt;
&lt;p&gt;在本教程中，您将从以下 CSV 文件导入数据：&lt;/p&gt;
&lt;h3&gt;persons.csv 内容:&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-csv&quot;&gt;&lt;code&gt;id,name
1,Charlie Sheen  
2,Michael Douglas
3,Martin Sheen
4,Morgan Freeman
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;persons.csv 文件包含 id 和 name 两列。每行代表一个人,具有唯一 id 和姓名。&lt;/p&gt;
&lt;h3&gt;movies.csv 内容:&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-csv&quot;&gt;&lt;code&gt;id,title,country,year
1,Wall Street,USA,1987
2,The American President,USA,1995
3,The Shawshank Redemption,USA,1994
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;movies.csv 文件包含 id、title、country 和 year 列。每行代表一部电影,具有唯一 id、标题、原产国和发行年份。&lt;/p&gt;
&lt;h3&gt;roles.csv 内容:&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-csv&quot;&gt;&lt;code&gt;personId,movieId,role
1,1,Bud Fox
3,1,Carl Fox 
2,1,Gordon Gekko
3,2,A.J. MacInerney
2,2,President Andrew Shepherd
4,3,Ellis Boyd &amp;#x27;Red&amp;#x27; Redding
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;roles.csv 文件包含 personId、movieId 和 role 列。每行代表一个角色，包含人物 id(来自 persons.csv)和电影 id(来自 movies.csv)的关系数据。&lt;/p&gt;
&lt;h2&gt;图模型&lt;/h2&gt;
&lt;p&gt;数据模型如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/getting-started-load-csv01-arr.svg&quot; alt=&quot;image&quot;&gt;(插入图1)&lt;/p&gt;
&lt;p&gt;基于 CSV 文件数据的结果图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/getting-started-load-csv02-arr.svg&quot; alt=&quot;image&quot;&gt;(插入图2)&lt;/p&gt;
&lt;h2&gt;前提条件&lt;/h2&gt;
&lt;p&gt;本教程使用 Linux 或 macOS 压缩包安装。&lt;/p&gt;
&lt;p&gt;假设您的当前工作目录是压缩包安装的 &amp;lt;neo4j-home&amp;gt; 目录，且 CSV 文件位于默认导入目录中。&lt;/p&gt;
&lt;p&gt;其他安装的默认目录请参见操作手册 → 文件位置。&lt;/p&gt;
&lt;p&gt;导入位置可以通过操作手册 → server.directories.import 配置。&lt;/p&gt;
&lt;h2&gt;准备数据库&lt;/h2&gt;
&lt;p&gt;导入数据之前，您应该通过创建索引和约束来准备要使用的数据库。&lt;/p&gt;
&lt;p&gt;您应该通过在 Person 和 Movie 节点上创建约束来确保它们具有唯一的 id 属性。&lt;/p&gt;
&lt;p&gt;创建唯一约束也会隐式创建索引。通过为 id 属性建立索引，节点查找(如通过 MATCH)将快得多。&lt;/p&gt;
&lt;p&gt;另外，为 country 名称创建索引以实现快速查找也是个好主意。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;启动 neo4j：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint language-bash&quot;&gt;&lt;code&gt;bin&amp;#x2F;neo4j start
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;默认用户名是 neo4j，密码是 neo4j。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建约束使每个 Person 节点具有唯一的 id 属性：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使用 Neo4j Browser：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE CONSTRAINT personIdConstraint FOR (person:Person) REQUIRE person.id IS UNIQUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或使用 Neo4j Cypher Shell：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-bash&quot;&gt;&lt;code&gt;bin&amp;#x2F;cypher-shell --database=neo4j &amp;quot;CREATE CONSTRAINT personIdConstraint FOR (person:Person) REQUIRE person.id IS UNIQUE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;创建约束使每个 Movie 节点具有唯一的 id 属性：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使用 Neo4j Browser：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE CONSTRAINT movieIdConstraint FOR (movie:Movie) REQUIRE movie.id IS UNIQUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或使用 Neo4j Cypher Shell：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-bash&quot;&gt;&lt;code&gt;bin&amp;#x2F;cypher-shell --database=neo4j &amp;quot;CREATE CONSTRAINT movieIdConstraint FOR (movie:Movie) REQUIRE movie.id IS UNIQUE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;为 Country 节点的 name 属性创建索引：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使用 Neo4j Browser：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE INDEX FOR (c:Country) ON (c.name)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或使用 Neo4j Cypher Shell：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-bash&quot;&gt;&lt;code&gt;bin&amp;#x2F;cypher-shell --database=neo4j &amp;quot;CREATE INDEX FOR (c:Country) ON (c.name)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;使用 LOAD CSV 导入数据&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;从 persons.csv 文件加载数据：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;使用 Neo4j Browser：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;LOAD CSV WITH HEADERS FROM &amp;quot;file:&amp;#x2F;&amp;#x2F;&amp;#x2F;persons.csv&amp;quot; AS csvLine
CREATE (p:Person {id: toInteger(csvLine.id), name: csvLine.name})
&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;从 movies.csv 文件加载数据：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;LOAD CSV WITH HEADERS FROM &amp;quot;file:&amp;#x2F;&amp;#x2F;&amp;#x2F;movies.csv&amp;quot; AS csvLine
MERGE (country:Country {name: csvLine.country})
CREATE (movie:Movie {id: toInteger(csvLine.id), title: csvLine.title, year:toInteger(csvLine.year)})
CREATE (movie)-[:ORIGIN]-&amp;gt;(country)
&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;从 roles.csv 文件加载数据：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;:auto LOAD CSV WITH HEADERS FROM &amp;#x27;file:&amp;#x2F;&amp;#x2F;&amp;#x2F;roles.csv&amp;#x27; AS csvLine
CALL {
 WITH csvLine
 MATCH (person:Person {id: toInteger(csvLine.personId)}), (movie:Movie {id: toInteger(csvLine.movieId)})
CREATE (person)-[:ACTED_IN {role: csvLine.role}]-&amp;gt;(movie)
} IN TRANSACTIONS OF 2 ROWS
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;导入数据&lt;/h2&gt;
&lt;p&gt;使用以下命令检查具有关系的所有节点：&lt;/p&gt;
&lt;p&gt;使用 Neo4j Browser：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (n)-[r]-&amp;gt;(m) RETURN n, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或使用 Neo4j Cypher Shell：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-bash&quot;&gt;&lt;code&gt;bin&amp;#x2F;cypher-shell --database=neo4j &amp;#x27;MATCH (n)-[r]-&amp;gt;(m) RETURN n, r, m&amp;#x27;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;输出将显示所有节点及其关系。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Thu, 17 Apr 2025 07:03:46 GMT</pubDate></item><item><title>Neo4j官方教程：第16节， 如何扩展 Cypher</title><link>http://neo4j.com.cn/topic/67fcc77da755994623e85dc7</link><guid>http://neo4j.com.cn/topic/67fcc77da755994623e85dc7</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/procedures-functions/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/procedures-functions/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;如何扩展 Cypher&lt;/h1&gt;
&lt;p&gt;本指南介绍了如何创建、使用和部署用户定义的程序和函数，这是 Cypher®（Neo4j 的查询语言）的扩展机制。&lt;/p&gt;
&lt;h2&gt;扩展 Cypher&lt;/h2&gt;
&lt;p&gt;Cypher 是一种强大且富有表达力的语言，具有一流的图模式和集合支持。但有时您需要做更多的事情，如额外的图算法、并行化或自定义转换。&lt;/p&gt;
&lt;p&gt;Cypher 可以通过用户定义的程序和函数进行扩展，详见 Java 参考 → 用户定义程序和 Java 参考 → 用户定义函数。&lt;/p&gt;
&lt;p&gt;Neo4j 本身提供并使用自定义程序。Neo4j 浏览器公开的许多监控、自检和安全功能都是使用程序实现的。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/procedures-functions-bolt.jpg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Neo4j 中的程序和函数&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;函数是简单的计算/转换，返回单个值&lt;/li&gt;
&lt;li&gt;函数可以在任何表达式或谓词中使用&lt;/li&gt;
&lt;li&gt;程序是更复杂的操作，生成结果流&lt;/li&gt;
&lt;li&gt;程序可以生成、获取或计算数据，供 Cypher 查询的后续处理步骤使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要调用数据库中部署的程序，请使用 CALL 子句(详见 Cypher 手册 → CALL 程序)。&lt;/p&gt;
&lt;h2&gt;列出和使用 Neo4j 的函数和程序&lt;/h2&gt;
&lt;p&gt;Neo4j 带有多个内置程序。要了解更多信息，请参阅操作手册 → 程序。&lt;/p&gt;
&lt;p&gt;要列出 DBMS 中所有可用的函数和程序，使用以下 Cypher 命令：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;SHOW FUNCTIONS
SHOW PROCEDURES
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以参考 Cypher 速查表以快速了解如何使用这些命令。&lt;/p&gt;
&lt;p&gt;每个程序返回一列或多列数据。通过 YIELD 子句，可以选择这些列并设置别名，然后在 Cypher 查询中使用。&lt;/p&gt;
&lt;p&gt;像其他 Cypher 管理命令一样，SHOW PROCEDURES 可以与 Cypher 子句的子集一起使用，如下所示，我们按 ‘db.’ 前缀过滤并按名称排序返回结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;SHOW PROCEDURES
YIELD name, signature, description as text
WHERE name STARTS WITH &amp;#x27;db.&amp;#x27;
RETURN * ORDER BY name ASC
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面是另一个示例，展示如何按选定的类别（例如包）对可用程序进行分组：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;SHOW PROCEDURES 
YIELD name, signature, description
RETURN split(name,&amp;quot;.&amp;quot;)[0..-1] AS package, count(*) AS count,
       collect(split(name,&amp;quot;.&amp;quot;)[-1]) AS names
ORDER BY count DESC
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可用程序集取决于您的安装类型和配置设置。结果可能如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;count&lt;/th&gt;
&lt;th&gt;names&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;[“dbms”]&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;[“checkConfigValue”, “components”, “info”,…]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[“db”]&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;[“awaitIndex”, “awaitIndexes”, “checkpoint”,…]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[“db”,“stats”]&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;[“clear”, “collect”, “retrieve”,…]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[“dbms”, “cluster”]&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;[“checkConnectivity”, “cordonServer”, “protocols”,…]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[“db”, “index”, “fulltext”]&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;[“awaitEventuallyConsistentIndexRefresh”, “listAvailableAnalyzers”,…]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;用户定义的函数用 Java 编写，部署到数据库中，其调用方式与其他 Cypher 函数相同。可以开发和使用两种主要类型的函数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户定义的标量函数&lt;/li&gt;
&lt;li&gt;用户定义的聚合函数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;详细信息请参见 Cypher 手册 → 用户定义函数。&lt;/p&gt;
&lt;p&gt;您可以将任何程序库部署到自管理服务器，以使用其他程序和函数。&lt;/p&gt;
&lt;p&gt;另请查看 Neo4j Java 参考中的程序部分。&lt;/p&gt;
&lt;h2&gt;部署程序和函数&lt;/h2&gt;
&lt;p&gt;如果您构建自己的程序或从社区项目下载程序，它们会打包在 JAR 文件中。您可以将该文件复制到 Neo4j 服务器的 $NEO4J_HOME/plugins 目录并重启。&lt;/p&gt;
&lt;p&gt;由于程序和函数使用低级 Java API，它们可以访问所有 Neo4j 内部组件以及文件系统和机器。这就是为什么您应该了解部署哪些程序以及原因。只安装来自可信源的程序。如果它们是开源的，请检查其源代码，最好自己构建。&lt;/p&gt;
&lt;p&gt;有关如何确保这些附加组件安全性的最佳实践，请参见操作手册 → 保护扩展。&lt;/p&gt;
&lt;p&gt;某些程序和函数可用于自管理的 Neo4j 企业版和社区版。
本节中描述的自定义代码与 AuraDB 不兼容。
在 Neo4j AuraDB 中，可用的程序和函数仅限于内置程序和函数以及 APOC Core 库的子集。&lt;/p&gt;
&lt;h2&gt;程序和函数库&lt;/h2&gt;
&lt;p&gt;APOC Core 库为您提供了一组有用的 Cypher 程序，以增强数据集成、图算法和数据转换等领域的功能。&lt;/p&gt;
&lt;p&gt;例如，用于格式化和解析不同分辨率时间戳的函数：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;RETURN apoc.date.format(timestamp()) as time,
       apoc.date.format(timestamp(),&amp;#x27;ms&amp;#x27;,&amp;#x27;yyyy-MM-dd&amp;#x27;) as date,
       apoc.date.parse(&amp;#x27;13.01.1975&amp;#x27;,&amp;#x27;s&amp;#x27;,&amp;#x27;dd.MM.yyyy&amp;#x27;) as unixtime,
       apoc.date.parse(&amp;#x27;2017-01-05 13:03:07&amp;#x27;) as millis
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;time&lt;/th&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;unixtime&lt;/th&gt;
&lt;th&gt;millis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“2017-01-05 13:06:39”&lt;/td&gt;
&lt;td&gt;“2017-01-05”&lt;/td&gt;
&lt;td&gt;158803200&lt;/td&gt;
&lt;td&gt;1483621387000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在我们的 Neo4j Labs 项目中，您可以找到由社区和员工构建的库集。看看已有的内容，很多需求已经被覆盖，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;索引操作&lt;/li&gt;
&lt;li&gt;数据库/API 集成&lt;/li&gt;
&lt;li&gt;图重构&lt;/li&gt;
&lt;li&gt;导入和导出&lt;/li&gt;
&lt;li&gt;空间索引查找&lt;/li&gt;
&lt;li&gt;RDF 导入和导出&lt;/li&gt;
&lt;li&gt;等等&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;社区和 Neo4j Labs 项目不受官方支持，我们不提供任何 SLA 或向后兼容性和弃用的保证。&lt;/p&gt;
&lt;h2&gt;开发自己的程序和函数&lt;/h2&gt;
&lt;p&gt;您可以在 Neo4j Java 参考中找到有关编写和测试程序的详细信息。&lt;/p&gt;
&lt;p&gt;示例 GitHub 存储库包含详细的文档和注释，您可以直接克隆并用作起点。&lt;/p&gt;
&lt;p&gt;以下是一些初步提示。&lt;/p&gt;
&lt;p&gt;用户定义的函数比较简单，让我们从它们开始：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@UserFunction&lt;/code&gt; 注解的公共 Java 类中的方法&lt;/li&gt;
&lt;li&gt;默认名称是包名.方法名&lt;/li&gt;
&lt;li&gt;返回单个值&lt;/li&gt;
&lt;li&gt;只读&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用户定义的程序类似：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@Procedure&lt;/code&gt; 注解的 Java 方法&lt;/li&gt;
&lt;li&gt;带有附加模式属性(READ, WRITE, DBMS)&lt;/li&gt;
&lt;li&gt;返回具有公共字段的简单对象的 Java 8 流&lt;/li&gt;
&lt;li&gt;这些字段名称转换为可用于 YIELD 的结果列&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些特性对两者都有效：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;@Name&lt;/code&gt; 注解的参数(带可选默认值)&lt;/li&gt;
&lt;li&gt;可以使用注入的 &lt;code&gt;@Context public GraphDatabaseService&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在 Cypher 语句的事务中运行&lt;/li&gt;
&lt;li&gt;支持的参数和结果类型有：Long、Double、Boolean、String、Node、Relationship、Path、Object&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 14 Apr 2025 08:29:49 GMT</pubDate></item><item><title>Neo4j官方教程：第15节，日期、日期时间和持续时间</title><link>http://neo4j.com.cn/topic/67fcc47aa755994623e85dc6</link><guid>http://neo4j.com.cn/topic/67fcc47aa755994623e85dc6</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/dates-datetimes-durations/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/dates-datetimes-durations/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;日期、日期时间和持续时间&lt;/h1&gt;
&lt;h2&gt;创建和更新值&lt;/h2&gt;
&lt;p&gt;让我们首先创建一些具有 &lt;code&gt;Datetime&lt;/code&gt; 属性的节点。我们可以通过执行以下 Cypher® 查询来执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;UNWIND [
    { title: &amp;quot;Cypher Basics I&amp;quot;,
      created: datetime(&amp;quot;2019-06-01T18:40:32.142+0100&amp;quot;),
      datePublished: date(&amp;quot;2019-06-01&amp;quot;),
      readingTime: {minutes: 2, seconds: 15} },
    { title: &amp;quot;Cypher Basics II&amp;quot;,
      created: datetime(&amp;quot;2019-06-02T10:23:32.122+0100&amp;quot;),
      datePublished: date(&amp;quot;2019-06-02&amp;quot;),
      readingTime: {minutes: 2, seconds: 30} },
    { title: &amp;quot;Dates, Datetimes, and Durations in Neo4j&amp;quot;,
      created: datetime(),
      datePublished: date(),
      readingTime: {minutes: 3, seconds: 30} }
] AS articleProperties

CREATE (article:Article {title: articleProperties.title})
SET article.created = articleProperties.created,
    article.datePublished = articleProperties.datePublished,
    article.readingTime = duration(articleProperties.readingTime)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在此查询中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;created&lt;/code&gt; 属性是一个 &lt;code&gt;DateTime&lt;/code&gt; 类型，等于执行查询时的时间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;date&lt;/code&gt; 属性是一个 &lt;code&gt;Date&lt;/code&gt; 类型，等于执行查询时的日期。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readingTime&lt;/code&gt; 是一个 &lt;code&gt;Duration&lt;/code&gt; 类型，为 3 分 30 秒。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也许我们想对此文章节点进行一些更改以更新 &lt;code&gt;datePublished&lt;/code&gt; 和 &lt;code&gt;readingTime&lt;/code&gt; 属性。&lt;/p&gt;
&lt;p&gt;我们已决定在下周而不是今天发布该文章，因此我们想进行更改。如果我们想使用支持的格式创建一个新的 &lt;code&gt;Date&lt;/code&gt; 类型，我们可以使用以下查询来执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article {title: &amp;quot;Dates, Datetimes, and Durations in Neo4j&amp;quot;})
SET article.datePublished = date(&amp;quot;2019-09-30&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;但是，如果我们想基于不支持的格式创建 &lt;code&gt;Date&lt;/code&gt; 类型怎么办？为此，我们将使用 APOC 库中的函数来解析字符串。&lt;/p&gt;
&lt;p&gt;以下查询将不支持的数据格式解析为基于毫秒的时间戳，从该时间戳创建一个 &lt;code&gt;Datetime&lt;/code&gt;，然后从该 &lt;code&gt;Datetime&lt;/code&gt; 创建一个 &lt;code&gt;Date&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;WITH apoc.date.parse(&amp;quot;Sun, 29 September 2019&amp;quot;, &amp;quot;ms&amp;quot;, &amp;quot;EEE, dd MMMM yyyy&amp;quot;) AS ms
MATCH (article:Article {title: &amp;quot;Dates, Datetimes, and Durations in Neo4j&amp;quot;})
SET article.datePublished = date(datetime({epochmillis: ms}))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;我们可以使用相同的方法来更新 &lt;code&gt;created&lt;/code&gt; 属性。我们唯一需要更改的是我们不需要将 &lt;code&gt;Datetime&lt;/code&gt; 类型转换为 &lt;code&gt;Date&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;WITH apoc.date.parse(&amp;quot;25 September 2019 06:29:39&amp;quot;, &amp;quot;ms&amp;quot;, &amp;quot;dd MMMM yyyy HH:mm:ss&amp;quot;) AS ms
MATCH (article:Article {title: &amp;quot;Dates, Datetimes, and Durations in Neo4j&amp;quot;})
SET article.created = datetime({epochmillis: ms})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;也许我们还决定阅读时间实际上将比我们最初想象的要多一分钟。我们可以使用以下查询更新 &lt;code&gt;readingTime&lt;/code&gt; 属性：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article {title: &amp;quot;Dates, Datetimes, and Durations in Neo4j&amp;quot;})
SET article.readingTime =  article.readingTime + duration({minutes: 1})
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;格式化值&lt;/h2&gt;
&lt;p&gt;现在我们要编写一个查询来返回我们的文章。我们可以通过执行以下查询来执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 1. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Dates, Datetimes, and Durations in Neo4j”&lt;/td&gt;
&lt;td&gt;2019-09-25T06:29:39Z&lt;/td&gt;
&lt;td&gt;2019-09-29&lt;/td&gt;
&lt;td&gt;P0M0DT270S&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果我们想格式化这些值，我们可以使用 APOC 库中的时间函数。以下查询将每个时间类型格式化为更友好的格式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
RETURN article.title AS title,
       apoc.temporal.format(article.created, &amp;quot;dd MMMM yyyy HH:mm&amp;quot;) AS created,
       apoc.temporal.format(article.datePublished,&amp;quot;dd MMMM yyyy&amp;quot;) AS datePublished,
       apoc.temporal.format(article.readingTime, &amp;quot;mm:ss&amp;quot;) AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 2. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Dates, Datetimes, and Durations in Neo4j”&lt;/td&gt;
&lt;td&gt;“25 September 2019 06:29”&lt;/td&gt;
&lt;td&gt;“29 September 2019”&lt;/td&gt;
&lt;td&gt;“04:30”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;比较和过滤值&lt;/h2&gt;
&lt;p&gt;如果我们想根据这些时间值过滤我们的文章怎么办？&lt;/p&gt;
&lt;p&gt;让我们首先找到 2019 年 6 月 1 日发布的文章。以下查询执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE article.datePublished = date({year: 2019, month: 6, day: 1})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 3. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics I”&lt;/td&gt;
&lt;td&gt;2019-06-01T18:40:32.142+01:00&lt;/td&gt;
&lt;td&gt;2019-06-01&lt;/td&gt;
&lt;td&gt;P0M0DT135S&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果我们想找到 2019 年 6 月发布的所有文章怎么办？我们可以编写以下查询来执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE article.datePublished = date({year: 2019, month: 6})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果我们运行此查询，我们将获得以下结果：&lt;/p&gt;
&lt;p&gt;表 4. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics I”&lt;/td&gt;
&lt;td&gt;2019-06-01T18:40:32.142+01:00&lt;/td&gt;
&lt;td&gt;2019-06-01&lt;/td&gt;
&lt;td&gt;P0M0DT135S&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这似乎不对 - 2019 年 6 月 2 日发布的 Cypher Basics II 文章呢？我们这里的问题是 &lt;code&gt;date({year: 2019, month:6})&lt;/code&gt; 返回 2019-06-01，所以我们只找到了 2019 年 6 月 1 日发布的文章。&lt;/p&gt;
&lt;p&gt;我们需要调整我们的查询以查找 2019 年 6 月 1 日至 2019 年 7 月 1 日之间发布的文章。以下查询执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE date({year: 2019, month: 7}) &amp;gt; article.datePublished &amp;gt;= date({year: 2019, month: 6})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 5. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics I”&lt;/td&gt;
&lt;td&gt;2019-06-01T18:40:32.142+01:00&lt;/td&gt;
&lt;td&gt;2019-06-01&lt;/td&gt;
&lt;td&gt;P0M0DT135S&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics II”&lt;/td&gt;
&lt;td&gt;2019-06-02T10:23:32.122+01:00&lt;/td&gt;
&lt;td&gt;2019-06-02&lt;/td&gt;
&lt;td&gt;P0M0DT150S&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果我们想根据 &lt;code&gt;created&lt;/code&gt; 属性（存储 &lt;code&gt;Datetime&lt;/code&gt; 值）进行过滤怎么办？我们需要在过滤 &lt;code&gt;Datetime&lt;/code&gt; 值时采用与处理 &lt;code&gt;Date&lt;/code&gt; 值相同的方法。以下查询查找 2019 年 7 月之后创建的文章：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE article.created &amp;gt; datetime({year: 2019, month: 7})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 6. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Dates, Datetimes, and Durations in Neo4j”&lt;/td&gt;
&lt;td&gt;2019-09-25T06:04:39.072Z&lt;/td&gt;
&lt;td&gt;2019-09-25&lt;/td&gt;
&lt;td&gt;P0M0DT210S&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最后过滤持续时间。我们可能对可以在 3 分钟或更短时间内阅读的文章感兴趣。&lt;/p&gt;
&lt;p&gt;我们将从以下查询开始：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE article.readingTime &amp;lt;= duration(&amp;quot;PT3M&amp;quot;)
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;但是，该查询会导致以下输出：没有更改，没有记录。&lt;/p&gt;
&lt;p&gt;如果我们想比较持续时间，我们需要通过将这些持续时间添加到日期来进行比较。我们并不真正关心查询的日期，所以我们将使用当前时间来解决这个问题。我们可以通过调用 &lt;code&gt;datetime()&lt;/code&gt; 函数来获取当前时间。&lt;/p&gt;
&lt;p&gt;我们更新后的查询如下所示：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (article:Article)
WHERE datetime() + article.readingTime &amp;lt;= datetime() + duration(&amp;quot;PT3M&amp;quot;)
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;表 7. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;title&lt;/th&gt;
&lt;th&gt;created&lt;/th&gt;
&lt;th&gt;datePublished&lt;/th&gt;
&lt;th&gt;readingTime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics I”&lt;/td&gt;
&lt;td&gt;“01 June 2019 18:40”&lt;/td&gt;
&lt;td&gt;“01 June 2019”&lt;/td&gt;
&lt;td&gt;“02:15”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“Cypher Basics II”&lt;/td&gt;
&lt;td&gt;“02 June 2019 10:23”&lt;/td&gt;
&lt;td&gt;“02 June 2019”&lt;/td&gt;
&lt;td&gt;“02:30”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;资源&lt;/h2&gt;
&lt;p&gt;本节介绍了如何使用 APOC 库更有效地处理时间类型。以下是有关在 Neo4j 中使用时间类型的更多信息的资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cypher 中的时间（日期/时间）值&lt;/li&gt;
&lt;li&gt;APOC 库&lt;/li&gt;
&lt;li&gt;日期和时间转换&lt;/li&gt;
&lt;li&gt;时间函数&lt;/li&gt;
&lt;li&gt;开发人员博客：Cypher 侦探：处理日期，第 1 部分&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 14 Apr 2025 08:16:58 GMT</pubDate></item><item><title>Neo4j官方教程：第14节，定义模式</title><link>http://neo4j.com.cn/topic/67fcc2eba755994623e85dc5</link><guid>http://neo4j.com.cn/topic/67fcc2eba755994623e85dc5</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/schema/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/schema/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;定义模式&lt;/h1&gt;
&lt;h2&gt;示例图&lt;/h2&gt;
&lt;p&gt;首先创建一些数据以用于我们的示例：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (forrestGump:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994})
CREATE (robert:Person:Director {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951})
CREATE (tom:Person:Actor {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})
CREATE (tom)-[:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;]}]-&amp;gt;(forrestGump)
CREATE (robert)-[:DIRECTED]-&amp;gt;(forrestGump)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是生成的图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-schema-data-arr.svg&quot; alt=&quot;image&quot;&gt;
(插入图表链接)&lt;/p&gt;
&lt;h2&gt;使用索引&lt;/h2&gt;
&lt;p&gt;在图数据库中使用索引的主要原因是找到图遍历的起点。一旦找到该起点，遍历就会依赖于图内结构来实现高性能。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以随时添加索引。&lt;/li&gt;
&lt;li&gt;如果数据库中存在现有数据，则索引联机需要一些时间。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下查询创建一个索引，以加快在数据库中按名称查找演员的速度：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE INDEX example_index_1 FOR (a:Actor) ON (a.name)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在大多数情况下，在查询数据时无需指定索引，因为将自动使用适当的索引。&lt;/p&gt;
&lt;p&gt;可以使用索引提示在特定查询中指定要使用的索引。这是查询调优的几个选项之一，在 Cypher® 手册 → 查询调优 中有详细描述。&lt;/p&gt;
&lt;p&gt;例如，以下查询将自动使用 example_index_1：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (actor:Actor {name: &amp;#x27;Tom Hanks&amp;#x27;})
RETURN actor
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;复合索引是针对具有特定标签的所有节点的多个属性的索引。例如，以下语句将创建一个复合索引，该索引针对所有带有 &lt;code&gt;Actor&lt;/code&gt; 标签并且同时具有 &lt;code&gt;name&lt;/code&gt; 和 &lt;code&gt;born&lt;/code&gt; 属性的节点。请注意，由于带有 &lt;code&gt;Actor&lt;/code&gt; 标签且名称为“Keanu Reeves”的节点没有 &lt;code&gt;born&lt;/code&gt; 属性。因此，该节点不会添加到索引中。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE INDEX example_index_2 FOR (a:Actor) ON (a.name, a.born)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以使用 &lt;code&gt;SHOW INDEXES&lt;/code&gt; 查询数据库，以找出定义了哪些索引。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;SHOW INDEXES YIELD name, labelsOrTypes, properties, type
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+----------------------------------------------------------------+
| name              | labelsOrTypes | properties       | type    |
+----------------------------------------------------------------+
| &amp;#x27;example_index_1&amp;#x27; | [&amp;#x27;Actor&amp;#x27;]     | [&amp;#x27;name&amp;#x27;]         | &amp;#x27;BTREE&amp;#x27; |
| &amp;#x27;example_index_2&amp;#x27; | [&amp;#x27;Actor&amp;#x27;]     | [&amp;#x27;name&amp;#x27;, &amp;#x27;born&amp;#x27;] | &amp;#x27;BTREE&amp;#x27; |
+----------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在 Cypher 手册 → 索引 中了解有关索引的更多信息。&lt;/p&gt;
&lt;h2&gt;使用约束&lt;/h2&gt;
&lt;p&gt;约束用于确保数据符合域的规则。例如：&lt;/p&gt;
&lt;p&gt;“如果一个节点具有 &lt;code&gt;Actor&lt;/code&gt; 标签和 &lt;code&gt;name&lt;/code&gt; 属性，则 &lt;code&gt;name&lt;/code&gt; 的值在所有具有 &lt;code&gt;Actor&lt;/code&gt; 标签的节点中必须是唯一的”。&lt;/p&gt;
&lt;h3&gt;示例 1. 唯一性约束&lt;/h3&gt;
&lt;p&gt;此示例显示了如何为具有 &lt;code&gt;Movie&lt;/code&gt; 标签和 &lt;code&gt;title&lt;/code&gt; 属性的节点创建约束。该约束指定 &lt;code&gt;title&lt;/code&gt; 属性必须是唯一的。&lt;/p&gt;
&lt;p&gt;添加唯一性约束将隐式地在该属性上添加索引。如果删除约束，但仍然需要索引，则必须显式创建索引。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE CONSTRAINT constraint_example_1 FOR (movie:Movie) REQUIRE movie.title IS UNIQUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Neo4j 4.4 中更改了语法，旧语法是：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE CONSTRAINT constraint_example_1 ON (movie:Movie) ASSERT movie.title IS UNIQUE Deprecated
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以将约束添加到数据库中已存在数据的数据库。这要求现有数据符合正在添加的约束。&lt;/p&gt;
&lt;p&gt;您可以使用 &lt;code&gt;SHOW CONSTRAINTS&lt;/code&gt; Cypher 语法查询数据库以找出定义了哪些约束。&lt;/p&gt;
&lt;h3&gt;示例 2. 约束查询&lt;/h3&gt;
&lt;p&gt;此示例显示了一个 Cypher 查询，该查询返回为数据库定义的约束。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;SHOW CONSTRAINTS YIELD id, name, type, entityType, labelsOrTypes, properties, ownedIndexId
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+-----------------------------------------------------------------------------------------------------+
| id | name                   | type         | entityType | labelsOrTypes | properties | ownedIndexId |
+-----------------------------------------------------------------------------------------------------+
| 4  | &amp;#x27;constraint_example_1&amp;#x27; | &amp;#x27;UNIQUENESS&amp;#x27; | &amp;#x27;NODE&amp;#x27;     | [&amp;#x27;Movie&amp;#x27;]     | [&amp;#x27;title&amp;#x27;]  | 3            |
+-----------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上述约束适用于所有版本的 Neo4j。其他约束可用于 Neo4j 企业版。&lt;/p&gt;
&lt;p&gt;在 Cypher 手册 → 约束 中了解有关约束的更多信息。&lt;/p&gt;
&lt;p&gt;Similar code found with 2 license types&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 14 Apr 2025 08:10:19 GMT</pubDate></item><item><title>Neo4j官方教程：第13节， Cypher 中的子查询</title><link>http://neo4j.com.cn/topic/67fcc245a755994623e85dc4</link><guid>http://neo4j.com.cn/topic/67fcc245a755994623e85dc4</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/subqueries/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/subqueries/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Cypher 中的子查询&lt;/h1&gt;
&lt;h2&gt;回顾我们的示例图&lt;/h2&gt;
&lt;p&gt;我们所有的代码示例将继续使用我们之前使用过的其中一个图示例，但包括更多数据以用于此页面上的查询。下图是新图，一个由人员、他们工作的公司以及他们喜欢的技术组成的网络。&lt;/p&gt;
&lt;p&gt;我们添加了一个 &lt;code&gt;Person&lt;/code&gt; 节点（蓝色），该节点 &lt;code&gt;WORKS_FOR&lt;/code&gt; 一个 &lt;code&gt;Company&lt;/code&gt; 节点（红色）并且 &lt;code&gt;LIKES&lt;/code&gt; 一个 &lt;code&gt;Technology&lt;/code&gt; 节点（绿色）：Ryan 为 Company Z 工作并且喜欢 Python。您可以在图的右侧找到此数据。&lt;/p&gt;
&lt;p&gt;回顾一下，每个人也可能与其他人有多个 &lt;code&gt;IS_FRIENDS_WITH&lt;/code&gt; 关系。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/people-technologies-graph-arr1.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;图 1. 人员、他们工作的公司以及他们喜欢的技术的网络&lt;/p&gt;
&lt;p&gt;您可以使用以下 Cypher® 查询创建此数据集：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (diana:Person {name: &amp;quot;Diana&amp;quot;})-[:LIKES]-&amp;gt;(query:Technology {type: &amp;quot;Query Languages&amp;quot;})
CREATE (melissa:Person {name: &amp;quot;Melissa&amp;quot;, twitter: &amp;quot;@melissa&amp;quot;})-[:LIKES]-&amp;gt;(query)
CREATE (dan:Person {name: &amp;quot;Dan&amp;quot;, twitter: &amp;quot;@dan&amp;quot;, yearsExperience: 6})-[:LIKES]-&amp;gt;(etl:Technology {type: &amp;quot;Data ETL&amp;quot;})&amp;lt;-[:LIKES]-(melissa)
CREATE (xyz:Company {name: &amp;quot;XYZ&amp;quot;})&amp;lt;-[:WORKS_FOR]-(sally:Person {name: &amp;quot;Sally&amp;quot;, yearsExperience: 4})-[:LIKES]-&amp;gt;(integrations:Technology {type: &amp;quot;Integrations&amp;quot;})&amp;lt;-[:LIKES]-(dan)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(john:Person {name: &amp;quot;John&amp;quot;, yearsExperience: 5, birthdate: &amp;quot;1985-04-04&amp;quot;})-[:LIKES]-&amp;gt;(java:Technology {type: &amp;quot;Java&amp;quot;})
CREATE (john)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer:Person {name: &amp;quot;Jennifer&amp;quot;, twitter: &amp;quot;@jennifer&amp;quot;, yearsExperience: 5, birthdate: &amp;quot;1988-01-01&amp;quot;})-[:LIKES]-&amp;gt;(java)
CREATE (john)-[:WORKS_FOR]-&amp;gt;(xyz)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(melissa)
CREATE (joe:Person {name: &amp;quot;Joe&amp;quot;, birthdate: &amp;quot;1988-08-08&amp;quot;})-[:LIKES]-&amp;gt;(query)
CREATE (mark:Person {name: &amp;quot;Mark&amp;quot;, twitter: &amp;quot;@mark&amp;quot;})
CREATE (ann:Person {name: &amp;quot;Ann&amp;quot;})
CREATE (x:Company {name: &amp;quot;Company X&amp;quot;})&amp;lt;-[:WORKS_FOR]-(diana)&amp;lt;-[:IS_FRIENDS_WITH]-(joe)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)-[:LIKES]-&amp;gt;(graphs:Technology {type: &amp;quot;Graphs&amp;quot;})&amp;lt;-[:LIKES]-(jennifer)-[:WORKS_FOR]-&amp;gt;(:Company {name: &amp;quot;Neo4j&amp;quot;})
CREATE (ann)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)
CREATE (john)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Application Development&amp;quot;})&amp;lt;-[:LIKES]-(ann)-[:IS_FRIENDS_WITH]-&amp;gt;(dan)-[:WORKS_FOR]-&amp;gt;(abc:Company {name: &amp;quot;ABC&amp;quot;})
CREATE (ann)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (a:Company {name: &amp;quot;Company A&amp;quot;})&amp;lt;-[:WORKS_FOR]-(melissa)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(diana)
CREATE (:Technology {type: &amp;quot;Python&amp;quot;})&amp;lt;-[:LIKES]-(:Person {name: &amp;quot;Ryan&amp;quot;})-[:WORKS_FOR]-&amp;gt;(:Company {name: &amp;quot;Company Z&amp;quot;})
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;子查询简介&lt;/h2&gt;
&lt;p&gt;子查询是在 Neo4j 4.0 中引入的。&lt;/p&gt;
&lt;p&gt;有关如何使用它们的详细信息，请转到 Cypher 手册 → 子查询。&lt;/p&gt;
&lt;p&gt;以下类型的子查询在 Neo4j 中是可能的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EXISTS&lt;/code&gt; 子查询&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COUNT&lt;/code&gt; 子查询&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CALL {…​}&lt;/code&gt; 子查询子句&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CALL {…​} IN TRANSACTIONS&lt;/code&gt; 子查询子句&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COLLECT&lt;/code&gt; 子查询（在 5.6 中引入）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;EXISTS&lt;/code&gt;、&lt;code&gt;COUNT&lt;/code&gt; 和 &lt;code&gt;CALL {…​}&lt;/code&gt; 子查询在本节中介绍。&lt;/p&gt;
&lt;p&gt;要了解有关使用 &lt;code&gt;CALL {…​} IN TRANSACTIONS&lt;/code&gt; 的更多信息，请参阅以下教程中的代码示例，了解如何将 CSV 数据导入到 Neo4j 数据库中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;教程：导入数据&lt;/li&gt;
&lt;li&gt;将 CSV 数据导入到 Neo4j&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;COLLECT&lt;/code&gt; 子查询是在 Neo4j 5.6 中引入的。这是一种新型的子查询，用于将子查询的结果收集到列表中，以便可以执行进一步的操作，如 &lt;code&gt;DISTINCT&lt;/code&gt;、&lt;code&gt;ORDER BY&lt;/code&gt;、&lt;code&gt;LIMIT&lt;/code&gt; 和 &lt;code&gt;SKIP&lt;/code&gt;。&lt;code&gt;COLLECT&lt;/code&gt; 子查询与 &lt;code&gt;COUNT&lt;/code&gt; 和 &lt;code&gt;EXISTS&lt;/code&gt; 子查询的不同之处在于，最终的 &lt;code&gt;RETURN&lt;/code&gt; 子句是强制性的。&lt;code&gt;COLLECT&lt;/code&gt; 子查询中的 &lt;code&gt;RETURN&lt;/code&gt; 子句必须只返回一列。&lt;/p&gt;
&lt;h2&gt;Cypher 子查询&lt;/h2&gt;
&lt;p&gt;子查询是在其自身范围内执行的一组 Cypher 语句。子查询通常从外部封闭查询中调用。&lt;/p&gt;
&lt;p&gt;以下是关于子查询的一些重要事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;子查询返回 &lt;code&gt;RETURN&lt;/code&gt; 子句中变量引用的值。&lt;/li&gt;
&lt;li&gt;子查询不能返回与封闭查询中使用的变量同名的变量。&lt;/li&gt;
&lt;li&gt;您必须显式地将变量从封闭查询传递到子查询。&lt;/li&gt;
&lt;li&gt;子查询用大括号 (&lt;code&gt;{}&lt;/code&gt;) 划定。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在获取正确的结果一章的过滤模式部分中，您学习了如何基于模式进行过滤。例如，您可以编写以下查询来查找为 Neo4j 工作的人的朋友：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[r:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WHERE exists((p)-[:WORKS_FOR]-&amp;gt;(:Company {name: &amp;#x27;Neo4j&amp;#x27;}))
RETURN p, r, friend
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您在 Neo4j 浏览器中运行此查询，将返回以下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/friends-of-neo4j.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;图 2. 图格式的输出&lt;/p&gt;
&lt;p&gt;Cypher 子查询支持更强大的模式过滤。您可以不使用 &lt;code&gt;WHERE&lt;/code&gt; 子句中的 &lt;code&gt;exists&lt;/code&gt; 函数，而是使用 &lt;code&gt;EXISTS&lt;/code&gt; 子查询。您可以使用以下查询重现前面的示例：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[r:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WHERE EXISTS {
  MATCH (p)-[:WORKS_FOR]-&amp;gt;(:Company {name: &amp;#x27;Neo4j&amp;#x27;})
}
RETURN p, r, friend
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您将获得相同的结果，这很好，但到目前为止，您所实现的只是用更多的代码做同样的事情！&lt;/p&gt;
&lt;p&gt;接下来，让我们编写一个子查询，该子查询的过滤能力比单独使用 &lt;code&gt;WHERE&lt;/code&gt; 子句或 &lt;code&gt;exists&lt;/code&gt; 函数所能实现的更强大。&lt;/p&gt;
&lt;p&gt;假设：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;您想找到为名称以“Company”开头的公司工作的人，并且他们喜欢至少一项被三个或更多人喜欢的技术。&lt;/li&gt;
&lt;li&gt;您不感兴趣知道这些技术是什么。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;您可以尝试使用以下查询来回答这个问题：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (person:Person)-[:WORKS_FOR]-&amp;gt;(company)
WHERE company.name STARTS WITH &amp;quot;Company&amp;quot;
AND (person)-[:LIKES]-&amp;gt;(t:Technology)
AND COUNT { (t)&amp;lt;-[:LIKES]-() } &amp;gt;= 3
RETURN person.name as person, company.name AS company;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您运行此查询，您将看到以下输出：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Variable &amp;#96;t&amp;#96; not defined (line 4, column 25 (offset: 112))
&amp;quot;AND (person)-[:LIKES]-&amp;gt;(t:Technology)&amp;quot;
                         ^
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以找到喜欢某项技术的人，但您无法检查是否至少有其他三个人也喜欢该技术，因为变量 &lt;code&gt;t&lt;/code&gt; 不在 &lt;code&gt;WHERE&lt;/code&gt; 子句的范围内。让我们将两个 &lt;code&gt;AND&lt;/code&gt; 语句移动到 &lt;code&gt;EXISTS&lt;/code&gt; 子查询块中，从而得到以下查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (person:Person)-[:WORKS_FOR]-&amp;gt;(company)
WHERE company.name STARTS WITH &amp;quot;Company&amp;quot;
AND EXISTS {
  MATCH (person)-[:LIKES]-&amp;gt;(t:Technology)
  WHERE COUNT { (t)&amp;lt;-[:LIKES]-() } &amp;gt;= 3
}
RETURN person.name as person, company.name AS company;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在您可以成功运行查询，该查询返回以下结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;person	company
&amp;quot;Melissa&amp;quot;	&amp;quot;CompanyA&amp;quot;
&amp;quot;Diana&amp;quot;	&amp;quot;CompanyX&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您回忆起本指南开头的图可视化，Ryan 是唯一另一个为名称以“Company”开头的公司工作的人。他已在此查询中被过滤掉，因为他喜欢的唯一技术是 Python，并且没有其他三个人喜欢 Python。&lt;/p&gt;
&lt;h2&gt;结果返回子查询&lt;/h2&gt;
&lt;p&gt;到目前为止，您已经学习了如何使用子查询来过滤掉结果，但这并没有完全显示它们的强大功能。您还可以使用子查询来返回结果。&lt;/p&gt;
&lt;p&gt;假设您要编写一个查询，查找喜欢 Java 或有多个朋友的人。除此之外，您希望按出生日期降序对结果进行排序。这可以使用 &lt;code&gt;UNION&lt;/code&gt; 子句和 &lt;code&gt;COUNT&lt;/code&gt; 子查询部分实现：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Java&amp;quot;})
RETURN p.name AS person, p.birthdate AS dob
ORDER BY dob DESC

UNION

MATCH (p:Person)
WHERE COUNT { (p)-[:IS_FRIENDS_WITH]-&amp;gt;() } &amp;gt; 1
RETURN p.name AS person, p.birthdate AS dob
ORDER BY dob DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您运行该查询，您将看到以下输出：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;person	dob
&amp;quot;Jennifer&amp;quot;	&amp;quot;1988-01-01&amp;quot;
&amp;quot;John&amp;quot;	&amp;quot;1985-04-04&amp;quot;
&amp;quot;Joe&amp;quot;	&amp;quot;1988-08-08&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您得到了正确的人。但是 &lt;code&gt;UNION&lt;/code&gt; 方法只允许我们按 &lt;code&gt;UNION&lt;/code&gt; 子句对结果进行排序，而不是对所有行进行排序。&lt;/p&gt;
&lt;p&gt;您可以尝试另一种方法，即分别执行每个子查询，并使用 &lt;code&gt;collect()&lt;/code&gt; 函数从每个部分收集人员。有些人喜欢 Java 并且有多个朋友，因此您需要在 &lt;code&gt;RETURN&lt;/code&gt; 子句中使用 &lt;code&gt;DISTINCT&lt;/code&gt; 运算符来删除重复项：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F; Find people who like Java
MATCH (p:Person)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Java&amp;quot;})
WITH collect(p) AS peopleWhoLikeJava

&amp;#x2F;&amp;#x2F; Find people with more than one friend
MATCH (p:Person)
WHERE COUNT { (p)-[:IS_FRIENDS_WITH]-&amp;gt;() } &amp;gt; 1
WITH collect(p) AS popularPeople, peopleWhoLikeJava
WITH popularPeople + peopleWhoLikeJava AS people

&amp;#x2F;&amp;#x2F; Unpack the collection of people and order by birthdate
UNWIND people AS p
RETURN DISTINCT p.name AS person, p.birthdate AS dob
ORDER BY dob DESC
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您运行该查询，您将获得以下输出：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;person	dob
&amp;quot;Joe&amp;quot;	&amp;quot;1988-08-08&amp;quot;
&amp;quot;Jennifer&amp;quot;	&amp;quot;1988-01-01&amp;quot;
&amp;quot;John&amp;quot;	&amp;quot;1985-04-04&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这种方法有效，但更难编写，因为您必须不断地将查询的各个部分传递到它的下一部分。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CALL {…​}&lt;/code&gt; 子句为您提供了两全其美的优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;您可以使用 &lt;code&gt;UNION&lt;/code&gt; 方法来运行各个查询并删除重复项。&lt;/li&gt;
&lt;li&gt;您可以在之后对结果进行排序。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们使用 &lt;code&gt;CALL {…​}&lt;/code&gt; 子句的查询如下所示：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CALL {
	MATCH (p:Person)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Java&amp;quot;})
	RETURN p

	UNION

	MATCH (p:Person)
	WHERE COUNT { (p)-[:IS_FRIENDS_WITH]-&amp;gt;() } &amp;gt; 1
	RETURN p
}
RETURN p.name AS person, p.birthdate AS dob
ORDER BY dob DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您运行该查询，您将获得以下输出：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;person	dob
&amp;quot;Joe&amp;quot;	&amp;quot;1988-08-08&amp;quot;
&amp;quot;Jennifer&amp;quot;	&amp;quot;1988-01-01&amp;quot;
&amp;quot;John&amp;quot;	&amp;quot;1985-04-04&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以进一步扩展查询以返回这些人喜欢的技术以及他们拥有的朋友。以下查询显示了如何执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CALL {
	MATCH (p:Person)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Java&amp;quot;})
	RETURN p

	UNION

	MATCH (p:Person)
	WHERE COUNT { (p)-[:IS_FRIENDS_WITH]-&amp;gt;() } &amp;gt; 1
	RETURN p
}
WITH p,
     [(p)-[:LIKES]-&amp;gt;(t) | t.type] AS technologies,
     [(p)-[:IS_FRIENDS_WITH]-&amp;gt;(f) | f.name] AS friends

RETURN p.name AS person, p.birthdate AS dob, technologies, friends
ORDER BY dob DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;person	dob	technologies	friends
&amp;quot;Joe&amp;quot;	&amp;quot;1988-08-08&amp;quot;	[&amp;quot;Query Languages&amp;quot;]	[&amp;quot;Mark&amp;quot;, &amp;quot;Diana&amp;quot;]
&amp;quot;Jennifer&amp;quot;	&amp;quot;1988-01-01&amp;quot;	[&amp;quot;Graphs&amp;quot;, &amp;quot;Java&amp;quot;]	[&amp;quot;Sally&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;John&amp;quot;, &amp;quot;Ann&amp;quot;, &amp;quot;Melissa&amp;quot;]
&amp;quot;John&amp;quot;	&amp;quot;1985-04-04&amp;quot;	[&amp;quot;Java&amp;quot;, &amp;quot;Application Development&amp;quot;]	[&amp;quot;Sally&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您还可以将聚合函数应用于子查询的结果。以下查询返回喜欢 Java 或有多个朋友的人中最年轻和最年长的人。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CALL {
	MATCH (p:Person)-[:LIKES]-&amp;gt;(:Technology {type: &amp;quot;Java&amp;quot;})
	RETURN p

	UNION

	MATCH (p:Person)
	WHERE COUNT { (p)-[:IS_FRIENDS_WITH]-&amp;gt;() } &amp;gt; 1
	RETURN p
}
RETURN min(p.birthdate) AS oldest, max(p.birthdate) AS youngest
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;oldest	youngest
&amp;quot;1985-04-04&amp;quot;	&amp;quot;1988-08-08&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;您已经了解了如何使用 &lt;code&gt;EXISTS {}&lt;/code&gt; 子查询编写复杂的过滤模式，以及如何使用 &lt;code&gt;CALL {}&lt;/code&gt; 子句执行返回结果的子查询。&lt;/p&gt;
&lt;p&gt;Similar code found with 1 license type&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 14 Apr 2025 08:07:33 GMT</pubDate></item><item><title>Neo4j官方教程：第12节，编写大型语句</title><link>http://neo4j.com.cn/topic/67f869905885e744204e1839</link><guid>http://neo4j.com.cn/topic/67f869905885e744204e1839</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/large-statements/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/large-statements/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;编写大型语句&lt;/h1&gt;
&lt;h2&gt;示例图&lt;/h2&gt;
&lt;p&gt;我们继续使用与之前相同的示例数据：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (matrix:Movie {title: &amp;#x27;The Matrix&amp;#x27;, released: 1997})
CREATE (cloudAtlas:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012})
CREATE (forrestGump:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994})
CREATE (keanu:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;, born: 1964})
CREATE (robert:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951})
CREATE (tom:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})
CREATE (tom)-[:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;]}]-&amp;gt;(forrestGump)
CREATE (tom)-[:ACTED_IN {roles: [&amp;#x27;Zachry&amp;#x27;]}]-&amp;gt;(cloudAtlas)
CREATE (robert)-[:DIRECTED]-&amp;gt;(forrestGump)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是生成的图：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-results01-arr.svg&quot; alt=&quot;image&quot;&gt;
(插入图表链接)&lt;/p&gt;
&lt;p&gt;图 1. 电影图&lt;/p&gt;
&lt;h2&gt;UNION&lt;/h2&gt;
&lt;p&gt;如果要组合具有相同结果结构的两个语句的结果，可以使用 &lt;code&gt;UNION [ALL]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;例如，以下查询列出了演员和导演：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (actor:Person)-[r:ACTED_IN]-&amp;gt;(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title
UNION
MATCH (director:Person)-[r:DIRECTED]-&amp;gt;(movie:Movie)
RETURN director.name AS name, type(r) AS type, movie.title AS title
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+-------------------------------------------------+
| name              | type       | title          |
+-------------------------------------------------+
| &amp;#x27;Tom Hanks&amp;#x27;       | &amp;#x27;ACTED_IN&amp;#x27; | &amp;#x27;Cloud Atlas&amp;#x27;  |
| &amp;#x27;Tom Hanks&amp;#x27;       | &amp;#x27;ACTED_IN&amp;#x27; | &amp;#x27;Forrest Gump&amp;#x27; |
| &amp;#x27;Robert Zemeckis&amp;#x27; | &amp;#x27;DIRECTED&amp;#x27; | &amp;#x27;Forrest Gump&amp;#x27; |
+-------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意，返回的列必须在所有子句中以相同的方式设置别名。&lt;/p&gt;
&lt;p&gt;上面的查询等效于这个更紧凑的查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (actor:Person)-[r:ACTED_IN|DIRECTED]-&amp;gt;(movie:Movie)
RETURN actor.name AS name, type(r) AS type, movie.title AS title
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;WITH&lt;/h2&gt;
&lt;p&gt;在 Cypher® 中，您可以将语句片段链接在一起，类似于在数据流管道中完成的方式。每个片段都处理前一个片段的输出，并且其结果可以馈送到下一个片段中。只有在 &lt;code&gt;WITH&lt;/code&gt; 子句中声明的列才在后续查询部分中可用。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WITH&lt;/code&gt; 子句用于组合各个部分并声明数据从一个部分流向另一个部分。&lt;code&gt;WITH&lt;/code&gt; 类似于 &lt;code&gt;RETURN&lt;/code&gt; 子句。不同之处在于 &lt;code&gt;WITH&lt;/code&gt; 子句不会完成查询，而是为下一部分准备输入。表达式、聚合、排序和分页可以以与 &lt;code&gt;RETURN&lt;/code&gt; 子句相同的方式使用。唯一的区别是所有列都必须设置别名。&lt;/p&gt;
&lt;p&gt;在以下示例中，收集某人出演的电影，然后过滤掉仅出现在一部电影中的电影。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (person:Person)-[:ACTED_IN]-&amp;gt;(m:Movie)
WITH person, count(*) AS appearances, collect(m.title) AS movies
WHERE appearances &amp;gt; 1
RETURN person.name, appearances, movies
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+-------------------------------------------------------------+
| person.name | appearances | movies                          |
+-------------------------------------------------------------+
| &amp;#x27;Tom Hanks&amp;#x27; | 2           | [&amp;#x27;Cloud Atlas&amp;#x27;, &amp;#x27;Forrest Gump&amp;#x27;] |
+-------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用 &lt;code&gt;WITH&lt;/code&gt; 子句，您可以将值从查询的一部分传递到另一部分。这允许您在查询中执行一些中间计算或操作以供以后使用。&lt;/p&gt;
&lt;p&gt;以下数据集用于演示下面的示例：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/people-technologies-graph-arr.svg&quot; alt=&quot;image&quot;&gt;
(插入图表链接)&lt;/p&gt;
&lt;p&gt;图 2. 图：人员、他们喜欢的技术以及他们工作的公司&lt;/p&gt;
&lt;p&gt;要重现该图，请运行 Cypher 代码：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (diana:Person {name: &amp;quot;Diana&amp;quot;})
CREATE (melissa:Person {name: &amp;quot;Melissa&amp;quot;, twitter: &amp;quot;@melissa&amp;quot;})
CREATE (dan:Person {name: &amp;quot;Dan&amp;quot;, twitter: &amp;quot;@dan&amp;quot;, yearsExperience: 6})
CREATE (sally:Person {name: &amp;quot;Sally&amp;quot;, yearsExperience: 4})
CREATE (john:Person {name: &amp;quot;John&amp;quot;, twitter: &amp;quot;@jennifer&amp;quot;, yearsExperience: 5})
CREATE (joe:Person {name: &amp;quot;Joe&amp;quot;})
CREATE (mark:Person {name: &amp;quot;Mark&amp;quot;, twitter: &amp;quot;@mark&amp;quot;})
CREATE (ann:Person {name: &amp;quot;Ann&amp;quot;})
CREATE (xyz:Company {name: &amp;quot;XYZ&amp;quot;})
CREATE (x:Company {name: &amp;quot;Company X&amp;quot;})
CREATE (a:Company {name: &amp;quot;Company A&amp;quot;})
CREATE (Neo4j:Company {name: &amp;quot;Neo4j&amp;quot;})
CREATE (abc:Company {name: &amp;quot;ABC&amp;quot;})
CREATE (query:Technology {type: &amp;quot;Query Languages&amp;quot;})
CREATE (etl:Technology {type: &amp;quot;Data ETL&amp;quot;})
CREATE (integrations:Technology {type: &amp;quot;Integrations&amp;quot;})
CREATE (graphs:Technology {type: &amp;quot;Graphs&amp;quot;})
CREATE (dev:Technology {type: &amp;quot;Application Development&amp;quot;})
CREATE (java:Technology {type: &amp;quot;Java&amp;quot;})
CREATE (diana)-[:LIKES]-&amp;gt;(query)
CREATE (melissa)-[:LIKES]-&amp;gt;(query)
CREATE (dan)-[:LIKES]-&amp;gt;(etl)&amp;lt;-[:LIKES]-(melissa)
CREATE (xyz)&amp;lt;-[:WORKS_FOR]-(sally)-[:LIKES]-&amp;gt;(integrations)&amp;lt;-[:LIKES]-(dan)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(john)-[:LIKES]-&amp;gt;(java)
CREATE (john)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:LIKES]-&amp;gt;(java)
CREATE (john)-[:WORKS_FOR]-&amp;gt;(xyz)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(melissa)
CREATE (joe)-[:LIKES]-&amp;gt;(query)
CREATE (x)&amp;lt;-[:WORKS_FOR]-(diana)&amp;lt;-[:IS_FRIENDS_WITH]-(joe)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(jennifer)-[:WORKS_FOR]-&amp;gt;(Neo4j)
CREATE (ann)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)
CREATE (john)-[:LIKES]-&amp;gt;(dev)&amp;lt;-[:LIKES]-(ann)-[:IS_FRIENDS_WITH]-&amp;gt;(dan)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (ann)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (a)&amp;lt;-[:WORKS_FOR]-(melissa)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(diana)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您必须在 &lt;code&gt;WITH&lt;/code&gt; 子句中指定您以后要使用的变量。只有这些变量会传递到查询的下一部分。有多种方法可以使用此功能（例如，计数、收集、过滤、限制结果）。&lt;/p&gt;
&lt;p&gt;有关如何使用 &lt;code&gt;WITH&lt;/code&gt; 的更多信息，请参阅 Cypher 手册部分。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: find and list the technologies people like
MATCH (a:Person)-[r:LIKES]-(t:Technology)
WITH a.name AS name, collect(t.type) AS technologies
RETURN name, technologies;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 9

+----------------------------------------------------------+
| name        | technologies                               |
+----------------------------------------------------------+
| &amp;#x27;Sally&amp;#x27;     | [&amp;#x27;Integrations&amp;#x27;]                           |
| &amp;#x27;Dan&amp;#x27;       | [&amp;#x27;Data ETL&amp;#x27;, &amp;#x27;Integrations&amp;#x27;]               |
| &amp;#x27;John&amp;#x27;      | [&amp;#x27;Java&amp;#x27;, &amp;#x27;Application Development&amp;#x27;]        |
| &amp;#x27;Diana&amp;#x27;     | [&amp;#x27;Query Languages&amp;#x27;, &amp;#x27;Graphs&amp;#x27;]              |
| &amp;#x27;Jennifer&amp;#x27;  | [&amp;#x27;Java&amp;#x27;, &amp;#x27;Graphs&amp;#x27;]                         |
| &amp;#x27;Ann&amp;#x27;       | [&amp;#x27;Application Development&amp;#x27;]                |
| &amp;#x27;Mark&amp;#x27;      | [&amp;#x27;Graphs&amp;#x27;]                                 |
| &amp;#x27;Joe&amp;#x27;       | [&amp;#x27;Query Languages&amp;#x27;]                        |
| &amp;#x27;Melissa&amp;#x27;   | [&amp;#x27;Query Languages&amp;#x27;, &amp;#x27;Data ETL&amp;#x27;, &amp;#x27;Graphs&amp;#x27;]  |
+----------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query2: find number of friends who have other friends
MATCH (p:Person)-[:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WITH p, collect(friend.name) AS friendsList, count{(friend)-[:IS_FRIENDS_WITH]-(:Person)} AS numberOfFoFs
WHERE numberOfFoFs &amp;gt; 1
RETURN p.name, friendsList, numberOfFoFs;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+---------------------------------------------------+-----------------+
| p.name        | friendList                        | numberOfFoFs    |
+---------------------------------------------------+-----------------+
| &amp;#x27;Joe&amp;#x27;         | [&amp;#x27;Mark&amp;#x27;]                          | 2               |
| &amp;#x27;Jennifer&amp;#x27;    | [&amp;#x27;Sally&amp;#x27;, &amp;#x27;John&amp;#x27;, &amp;#x27;Ann&amp;#x27;, &amp;#x27;Mark&amp;#x27;]  | 2               |
| &amp;#x27;John&amp;#x27;        | [&amp;#x27;Sally&amp;#x27;]                         | 2               |
+---------------------------------------------------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在第一个查询中，传递了人员姓名和收集的技术类型列表。因此，只有这些项目可以在 &lt;code&gt;RETURN&lt;/code&gt; 子句中引用。关系 ® 和人员出生日期都不能使用，因为这些值没有传递。&lt;/p&gt;
&lt;p&gt;在第二个查询中，只能引用 p 及其任何属性（姓名、出生日期、工作年限、Twitter）、朋友的集合（作为一个整体，而不是每个值）以及朋友的朋友的数量。由于这些值已在 &lt;code&gt;WITH&lt;/code&gt; 子句中传递，因此可以在 &lt;code&gt;WHERE&lt;/code&gt; 或 &lt;code&gt;RETURN&lt;/code&gt; 子句中使用它们。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WITH&lt;/code&gt; 要求传递的所有值都具有变量（如果它们还没有变量）。&lt;code&gt;Person&lt;/code&gt; 节点在 &lt;code&gt;MATCH&lt;/code&gt; 子句中被赋予变量 §，因此不需要在那里分配变量。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WITH&lt;/code&gt; 对于在查询之前设置参数也非常有用。在导入数据时，通常对参数键、URL 字符串和其他查询变量很有用。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Find people with 2-6 years of experience
WITH 2 AS experienceMin, 6 AS experienceMax
MATCH (p:Person)
WHERE experienceMin &amp;lt;= p.yearsExperience &amp;lt;= experienceMax
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 11 Apr 2025 01:00:00 GMT</pubDate></item><item><title>Neo4j官方教程：第11节，更新数据</title><link>http://neo4j.com.cn/topic/67f867115885e744204e1838</link><guid>http://neo4j.com.cn/topic/67f867115885e744204e1838</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自:&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/updating/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/updating/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;更新数据&lt;/h1&gt;
&lt;p&gt;之前您学习了如何在 Cypher® 中表示节点、关系、标签、属性和模式。本节通过介绍如何使用 Cypher 更新和删除数据，在您的知识中添加另一个层次。&lt;/p&gt;
&lt;p&gt;虽然这些是标准的 CRUD（创建、读取、更新和删除）操作，但与在其他类型的数据库中相比，某些功能在图中有所不同。当我们进行时，您可能会认识到一些相似之处和不同之处。&lt;/p&gt;
&lt;h2&gt;使用 Cypher 更新数据&lt;/h2&gt;
&lt;p&gt;您可能已经在数据中有一个节点或关系，但您想修改其属性。您可以通过匹配要查找的模式并使用 &lt;code&gt;SET&lt;/code&gt; 关键字来添加、删除或更新属性来执行此操作。&lt;/p&gt;
&lt;p&gt;我们继续使用以下数据集：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/people-technologies-graph-arr.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;图 1. 图：人员、他们工作的公司以及他们喜欢的技术&lt;/p&gt;
&lt;p&gt;要创建上述图，请运行 Cypher 查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (diana:Person {name: &amp;quot;Diana&amp;quot;})
CREATE (melissa:Person {name: &amp;quot;Melissa&amp;quot;, twitter: &amp;quot;@melissa&amp;quot;})
CREATE (dan:Person {name: &amp;quot;Dan&amp;quot;, twitter: &amp;quot;@dan&amp;quot;, yearsExperience: 6})
CREATE (sally:Person {name: &amp;quot;Sally&amp;quot;, yearsExperience: 4})
CREATE (john:Person {name: &amp;quot;John&amp;quot;, yearsExperience: 5})
CREATE (jennifer:Person {name: &amp;quot;Jennifer&amp;quot;, twitter: &amp;quot;@jennifer&amp;quot;, yearsExperience: 5})
CREATE (joe:Person {name: &amp;quot;Joe&amp;quot;})
CREATE (mark:Person {name: &amp;quot;Mark&amp;quot;, twitter: &amp;quot;@mark&amp;quot;})
CREATE (ann:Person {name: &amp;quot;Ann&amp;quot;})
CREATE (xyz:Company {name: &amp;quot;XYZ&amp;quot;})
CREATE (x:Company {name: &amp;quot;Company X&amp;quot;})
CREATE (a:Company {name: &amp;quot;Company A&amp;quot;})
CREATE (Neo4j:Company {name: &amp;quot;Neo4j&amp;quot;})
CREATE (abc:Company {name: &amp;quot;ABC&amp;quot;})
CREATE (query:Technology {type: &amp;quot;Query Languages&amp;quot;})
CREATE (etl:Technology {type: &amp;quot;Data ETL&amp;quot;})
CREATE (integrations:Technology {type: &amp;quot;Integrations&amp;quot;})
CREATE (graphs:Technology {type: &amp;quot;Graphs&amp;quot;})
CREATE (dev:Technology {type: &amp;quot;Application Development&amp;quot;})
CREATE (java:Technology {type: &amp;quot;Java&amp;quot;})
CREATE (diana)-[:LIKES]-&amp;gt;(query)
CREATE (melissa)-[:LIKES]-&amp;gt;(query)
CREATE (dan)-[:LIKES]-&amp;gt;(etl)&amp;lt;-[:LIKES]-(melissa)
CREATE (xyz)&amp;lt;-[:WORKS_FOR]-(sally)-[:LIKES]-&amp;gt;(integrations)&amp;lt;-[:LIKES]-(dan)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(john)-[:LIKES]-&amp;gt;(java)
CREATE (john)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:LIKES]-&amp;gt;(java)
CREATE (john)-[:WORKS_FOR]-&amp;gt;(xyz)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(melissa)
CREATE (joe)-[:LIKES]-&amp;gt;(query)
CREATE (x)&amp;lt;-[:WORKS_FOR]-(diana)&amp;lt;-[:IS_FRIENDS_WITH]-(joe)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(jennifer)-[:WORKS_FOR]-&amp;gt;(Neo4j)
CREATE (ann)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)
CREATE (john)-[:LIKES]-&amp;gt;(dev)&amp;lt;-[:LIKES]-(ann)-[:IS_FRIENDS_WITH]-&amp;gt;(dan)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (ann)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (a)&amp;lt;-[:WORKS_FOR]-(melissa)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(diana)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;到目前为止，使用上面的示例数据集，您可以更新 Jennifer 的节点以添加她的出生日期。下一个 Cypher 语句显示了如何执行此操作。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首先，您需要找到 Jennifer 的现有节点。&lt;/li&gt;
&lt;li&gt;接下来，使用 &lt;code&gt;SET&lt;/code&gt; 创建新属性（使用语法 &lt;code&gt;variable.property&lt;/code&gt;）并设置其值。&lt;/li&gt;
&lt;li&gt;最后，您可以返回 Jennifer 的节点以确保信息已正确更新。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Jennifer&amp;#x27;})
SET p.birthdate = date(&amp;#x27;1980-01-01&amp;#x27;)
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Set Properties: 1
Rows: 1

+------------------------------------------------------+
| p                                                    |
+------------------------------------------------------+
|(Person: {birthdate: &amp;#x27;1980-01-01&amp;#x27;, name: &amp;#x27;Jennifer&amp;#x27;}) |
+------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;有关使用 &lt;code&gt;date()&lt;/code&gt; 和其他时间函数的更多信息，请访问 Cypher 手册 → 时间函数。&lt;/p&gt;
&lt;p&gt;如果要更改 Jennifer 的出生日期，可以使用上面的同一查询再次找到 Jennifer 的节点，并在 &lt;code&gt;SET&lt;/code&gt; 子句中放入不同的日期。&lt;/p&gt;
&lt;p&gt;您还可以使用 &lt;code&gt;Company&lt;/code&gt; 节点更新 Jennifer 的 &lt;code&gt;WORKS_FOR&lt;/code&gt; 关系，以包括她开始在那里工作的年份。为此，您可以使用与上面类似的语法来更新节点。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Person {name: &amp;#x27;Jennifer&amp;#x27;})-[rel:WORKS_FOR]-(:Company {name: &amp;#x27;Neo4j&amp;#x27;})
SET rel.startYear = date({year: 2018})
RETURN rel
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Set Properties: 1
Rows: 1

+-----------------------------------------+
| rel                                     |
+-----------------------------------------+
| [:WORKS_FOR {startYear: &amp;#x27;2018-01-01&amp;#x27;}]  |
+-----------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果要返回上述查询的图视图，可以将变量添加到节点 &lt;code&gt;p:Person&lt;/code&gt; 和 &lt;code&gt;c:Company&lt;/code&gt;，并将返回行写为 &lt;code&gt;RETURN p, rel, c&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;使用 Cypher 删除数据&lt;/h2&gt;
&lt;p&gt;要介绍的另一个操作是如何在 Cypher 中删除数据。对于此操作，Cypher 使用 &lt;code&gt;DELETE&lt;/code&gt; 关键字删除节点和关系。它与其他语言（如 SQL）中删除数据非常相似，但有一个例外。&lt;/p&gt;
&lt;p&gt;由于 Neo4j 符合 ACID，因此如果节点仍具有关系，则无法删除该节点。如果可以这样做，那么您最终可能会得到指向空的关系和不完整的图。&lt;/p&gt;
&lt;h3&gt;删除关系&lt;/h3&gt;
&lt;p&gt;要删除关系，您需要找到要删除的关系的开始和结束节点，然后使用 &lt;code&gt;DELETE&lt;/code&gt; 关键字，如下面的代码块所示。让我们继续删除 Jennifer 和 Mark 之间的 &lt;code&gt;IS_FRIENDS_WITH&lt;/code&gt; 关系。我们稍后将在练习中重新添加此关系。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (j:Person {name: &amp;#x27;Jennifer&amp;#x27;})-[r:IS_FRIENDS_WITH]-&amp;gt;(m:Person {name: &amp;#x27;Mark&amp;#x27;})
DELETE r
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;+-----------------------------------------+
| Deleted Relationships: 1                |
| Rows: 0                                 |
+-----------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;删除节点&lt;/h3&gt;
&lt;p&gt;要删除没有任何关系的节点，您需要找到要删除的节点，然后使用 &lt;code&gt;DELETE&lt;/code&gt; 关键字，就像您对上面的关系所做的那样。您可以暂时删除 Mark 的节点，稍后再将其恢复。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Person {name: &amp;#x27;Mark&amp;#x27;})
DELETE m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;+-----------------------------------------+
| Deleted Nodes: 1                        |
| Rows: 0                                 |
+-----------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您错误地创建了一个空节点并且需要删除它，您可以使用以下 Cypher 语句来执行此操作：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (n)
WHERE id(n) = 5
DETACH DELETE n
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此语句不仅删除节点，还删除它具有的所有关系。要运行该语句，您应该知道节点的内部 ID。&lt;/p&gt;
&lt;h3&gt;删除节点及其关系&lt;/h3&gt;
&lt;p&gt;您可以运行单个语句来删除节点及其关系，而不是运行最后两个查询来删除 &lt;code&gt;IS_FRIENDS_WITH&lt;/code&gt; 关系和 Mark 的 &lt;code&gt;Person&lt;/code&gt; 节点。如上所述，Neo4j 符合 ACID，因此不允许删除仍具有关系的节点。使用 &lt;code&gt;DETACH DELETE&lt;/code&gt; 语法告诉 Cypher 删除节点具有的任何关系，并删除节点本身。&lt;/p&gt;
&lt;p&gt;该语句如下面的代码所示。首先，您在数据库中找到 Mark 的节点。然后，&lt;code&gt;DETACH DELETE&lt;/code&gt; 行删除 Mark 节点具有的任何现有关系，然后再删除该节点。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Person {name: &amp;#x27;Mark&amp;#x27;})
DETACH DELETE m
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;删除属性&lt;/h3&gt;
&lt;p&gt;您还可以删除属性，但您可以使用其他几种方法，而不是使用 &lt;code&gt;DELETE&lt;/code&gt; 关键字。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一种选择是在属性上使用 &lt;code&gt;REMOVE&lt;/code&gt;。这告诉 Neo4j 您要从节点中完全删除该属性，并且不再存储它。&lt;/li&gt;
&lt;li&gt;第二个选项是使用之前的 &lt;code&gt;SET&lt;/code&gt; 关键字将属性值设置为 null。与其他数据库模型不同，Neo4j 不存储空值。相反，它只存储对您的数据有意义的属性和值。这意味着您可以在图中的各种节点和关系上具有不同类型和数量的属性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了向您展示这两种选择，让我们看一下每种方法的代码。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;delete property using REMOVE keyword
MATCH (n:Person {name: &amp;#x27;Jennifer&amp;#x27;})
REMOVE n.birthdate

&amp;#x2F;&amp;#x2F;delete property with SET to null value
MATCH (n:Person {name: &amp;#x27;Jennifer&amp;#x27;})
SET n.birthdate = null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;+-----------------------------------------+
| Set Properties: 1                       |
| Rows: 0                                 |
+-----------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;使用 MERGE 避免重复数据&lt;/h2&gt;
&lt;p&gt;前面简要提到了 Cypher 中有一些方法可以避免创建重复数据。其中一种方法是使用 &lt;code&gt;MERGE&lt;/code&gt; 关键字。&lt;code&gt;MERGE&lt;/code&gt; 执行“选择或插入”操作，该操作首先检查数据库中是否存在数据。如果存在，则 Cypher 按原样返回它，或者对现有节点或关系进行您指定的任何更新。如果数据不存在，则 Cypher 将使用您指定的信息创建它。&lt;/p&gt;
&lt;h3&gt;在节点上使用 MERGE&lt;/h3&gt;
&lt;p&gt;首先，让我们通过使用下面的查询将 Mark 添加回我们的数据库来查看一个示例。您可以使用 &lt;code&gt;MERGE&lt;/code&gt; 来确保 Cypher 检查数据库中是否存在 Mark 的现有节点。由于您在前面的示例中删除了 Mark 的节点，因此 Cypher 将找不到现有匹配项，并将使用设置为“Mark”的名称属性创建一个新节点。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (mark:Person {name: &amp;#x27;Mark&amp;#x27;})
RETURN mark
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查询结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher_graph_mergeFriend-arr.svg&quot; alt=&quot;image&quot;&gt;
(插入图表链接)&lt;/p&gt;
&lt;p&gt;如果再次运行相同的语句，Cypher 这次将找到一个名称属性设置为 Mark 的现有节点，因此它将返回匹配的节点，而不会进行任何更改。&lt;/p&gt;
&lt;h3&gt;在关系上使用 MERGE&lt;/h3&gt;
&lt;p&gt;就像您使用 &lt;code&gt;MERGE&lt;/code&gt; 在 Cypher 中查找或创建节点一样，您可以执行相同的操作来查找或创建关系。让我们重新创建我们在先前示例中拥有的 Mark 和 Jennifer 之间的 &lt;code&gt;IS_FRIENDS_WITH&lt;/code&gt; 关系。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (j:Person {name: &amp;#x27;Jennifer&amp;#x27;})
MATCH (m:Person {name: &amp;#x27;Mark&amp;#x27;})
MERGE (j)-[r:IS_FRIENDS_WITH]-&amp;gt;(m)
RETURN j, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意，此处使用 &lt;code&gt;MATCH&lt;/code&gt; 在使用 &lt;code&gt;MERGE&lt;/code&gt; 查找或创建它们之间关系之前查找 Mark 的节点和 Jennifer 的节点。&lt;/p&gt;
&lt;h3&gt;为什么我们不使用单个语句？&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;MERGE&lt;/code&gt; 查找您指定的整个模式，以查看是返回现有模式还是创建新模式。如果整个模式（节点、关系和任何指定的属性）不存在，则 Cypher 会创建它。&lt;/p&gt;
&lt;p&gt;Cypher 永远不会在模式中产生匹配和创建的部分混合。为避免匹配和创建的混合，您需要在对可能要创建的任何元素执行合并之前，首先匹配模式的任何现有元素，就像我们在上面的语句中所做的那样。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher_graph_mergeFriendRel-arr.svg&quot; alt=&quot;image&quot;&gt;
(插入图表链接)&lt;/p&gt;
&lt;p&gt;仅供参考，导致重复项的 Cypher 语句如下。由于此模式（Jennifer IS_FRIENDS_WITH Mark）在数据库中不存在，因此 Cypher 会创建一个全新的模式 - 两个节点以及它们之间的关系。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;this statement will create duplicate nodes for Mark and Jennifer
MERGE (j:Person {name: &amp;#x27;Jennifer&amp;#x27;})-[r:IS_FRIENDS_WITH]-&amp;gt;(m:Person {name: &amp;#x27;Mark&amp;#x27;})
RETURN j, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;处理 MERGE 标准&lt;/h3&gt;
&lt;p&gt;也许您想使用 &lt;code&gt;MERGE&lt;/code&gt; 来确保您不创建重复项，但是如果创建了模式，您想初始化某些属性，如果仅匹配了模式，则要更新其他属性。在这种情况下，您可以将 &lt;code&gt;ON CREATE&lt;/code&gt; 或 &lt;code&gt;ON MATCH&lt;/code&gt; 与 &lt;code&gt;SET&lt;/code&gt; 关键字一起使用来处理这些情况。&lt;/p&gt;
&lt;p&gt;让我们看一个例子。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (m:Person {name: &amp;#x27;Mark&amp;#x27;})-[r:IS_FRIENDS_WITH]-(j:Person {name:&amp;#x27;Jennifer&amp;#x27;})
  ON CREATE SET r.since = date(&amp;#x27;2018-03-01&amp;#x27;)
  ON MATCH SET r.updated = date()
RETURN m, r, j
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;资源&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neo4j Cypher 手册：CREATE&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：SET&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：REMOVE&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：DELETE&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：MERGE&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：ON CREATE/ON MATCH&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 11 Apr 2025 00:49:21 GMT</pubDate></item><item><title>Neo4j官方教程：第10节，获取正确的结果</title><link>http://neo4j.com.cn/topic/67f5db4e455186f56d9f4135</link><guid>http://neo4j.com.cn/topic/67f5db4e455186f56d9f4135</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/results/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/results/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;获取正确的结果&lt;/h1&gt;
&lt;h2&gt;示例图&lt;/h2&gt;
&lt;p&gt;在本节中，使用了两个示例数据集。第一个图基于电影数据库。以下代码块可帮助您创建用于探索 Cypher® 查询的数据：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (matrix:Movie {title: &amp;#x27;The Matrix&amp;#x27;, released: 1997})
CREATE (cloudAtlas:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012})
CREATE (forrestGump:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994})
CREATE (keanu:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;, born: 1964})
CREATE (robert:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951})
CREATE (tom:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})
CREATE (tom)-[:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;]}]-&amp;gt;(forrestGump)
CREATE (tom)-[:ACTED_IN {roles: [&amp;#x27;Zachry&amp;#x27;]}]-&amp;gt;(cloudAtlas)
CREATE (robert)-[:DIRECTED]-&amp;gt;(forrestGump)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是生成的图：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-results01-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro results01 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;第二个数据集是一个由人员、他们工作的公司以及他们喜欢的技术组成的小型网络。您可以在以下章节中找到它的图像。&lt;/p&gt;
&lt;h2&gt;过滤结果&lt;/h2&gt;
&lt;p&gt;到目前为止，您已经匹配了图中的模式，并且总是返回您找到的所有结果。现在让我们看看过滤结果并仅返回您感兴趣的数据子集的选项。这些过滤器条件使用 &lt;code&gt;WHERE&lt;/code&gt; 子句表示。此子句允许使用任意数量的布尔表达式、谓词，并与 &lt;code&gt;AND&lt;/code&gt;、&lt;code&gt;OR&lt;/code&gt;、&lt;code&gt;XOR&lt;/code&gt; 和 &lt;code&gt;NOT&lt;/code&gt; 组合。最简单的谓词是比较；尤其是相等。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
WHERE m.title = &amp;#x27;The Matrix&amp;#x27;
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+------------------------------------------------+
| m                                              |
+------------------------------------------------+
| (:Movie {title: &amp;#x27;The Matrix&amp;#x27;, released: 1997}) |
+------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的查询使用 &lt;code&gt;WHERE&lt;/code&gt; 子句，等效于此查询，该查询在模式匹配中包含条件：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie {title: &amp;#x27;The Matrix&amp;#x27;})
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cypher 旨在具有灵活性，因此通常有多种编写查询的方法。&lt;/p&gt;
&lt;p&gt;其他选项包括数值比较、匹配正则表达式以及检查列表中是否存在值。&lt;/p&gt;
&lt;p&gt;以下示例中的 &lt;code&gt;WHERE&lt;/code&gt; 子句包括正则表达式匹配、大于比较以及测试以查看列表中是否存在值：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[r:ACTED_IN]-&amp;gt;(m:Movie)
WHERE p.name =~ &amp;#x27;K.+&amp;#x27; OR m.released &amp;gt; 2000 OR &amp;#x27;Neo&amp;#x27; IN r.roles
RETURN p, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;基于给定的逻辑运算符 &lt;code&gt;OR&lt;/code&gt; 和图模式 &lt;code&gt;(p:Person)-[r:ACTED_IN]-&amp;gt;(m:Movie)&lt;/code&gt;，查询结果必须满足以下要求之一：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;该人的名字以字母“K”开头。&lt;/li&gt;
&lt;li&gt;这部电影是在 2000 年之后发行的。&lt;/li&gt;
&lt;li&gt;角色是“Neo”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在我们的例子中，只有第二个条件匹配图模式 &lt;code&gt;(p:Person)-[r:ACTED_IN]-&amp;gt;(m:Movie)&lt;/code&gt;，因此输出如下：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+-------------------------------------------------------------------------------------------------------------------------------+
| p                                         | r                               | m                                               |
+-------------------------------------------------------------------------------------------------------------------------------+
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956}) | [:ACTED_IN {roles: [&amp;#x27;Zachry&amp;#x27;]}] | (:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012}) |
+-------------------------------------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;一个高级方面是模式可以用作谓词。&lt;code&gt;MATCH&lt;/code&gt; 扩展了匹配的模式的数量和形状，而模式谓词限制了当前结果集。它只允许满足指定模式的路径通过。正如您可以预期的那样，&lt;code&gt;NOT&lt;/code&gt; 的使用只允许不满足指定模式的路径通过。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:ACTED_IN]-&amp;gt;(m)
WHERE NOT (p)-[:DIRECTED]-&amp;gt;()
RETURN p, m
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+----------------------------------------------------------------------------------------------+
| p                                         | m                                                |
+----------------------------------------------------------------------------------------------+
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956}) | (:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012})  |
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956}) | (:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994}) |
+----------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在这里，您可以找到演员，因为他们支持 &lt;code&gt;ACTED_IN&lt;/code&gt; 关系，然后跳过那些曾经 &lt;code&gt;DIRECTED&lt;/code&gt; 任何电影的演员。&lt;/p&gt;
&lt;p&gt;还有更高级的过滤方法，例如列表谓词，这将在本节后面讨论。&lt;/p&gt;
&lt;h2&gt;查询值范围&lt;/h2&gt;
&lt;p&gt;经常有查询想要查找特定范围内的数据。日期或数字范围可用于检查特定时间线、年龄值或其他用途中的事件。&lt;/p&gt;
&lt;p&gt;此标准的语法与 SQL 和其他编程语言逻辑结构非常相似，用于检查值的范围。&lt;/p&gt;
&lt;p&gt;以下数据集用于演示这些情况的 Cypher 查询。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/people-companies-technologies-rel-property.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;people companies technologies rel property&quot;&gt;&lt;/p&gt;
&lt;p&gt;要重现数据集，请运行以下 Cypher 查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (diana:Person {name: &amp;quot;Diana&amp;quot;})
CREATE (melissa:Person {name: &amp;quot;Melissa&amp;quot;, twitter: &amp;quot;@melissa&amp;quot;})
CREATE (dan:Person {name: &amp;quot;Dan&amp;quot;, twitter: &amp;quot;@dan&amp;quot;, yearsExperience: 6})
CREATE (sally:Person {name: &amp;quot;Sally&amp;quot;, yearsExperience: 4})
CREATE (john:Person {name: &amp;quot;John&amp;quot;, yearsExperience: 5})
CREATE (jennifer:Person {name: &amp;quot;Jennifer&amp;quot;, twitter: &amp;quot;@jennifer&amp;quot;, yearsExperience: 5})
CREATE (joe:Person {name: &amp;quot;Joe&amp;quot;})
CREATE (mark:Person {name: &amp;quot;Mark&amp;quot;, twitter: &amp;quot;@mark&amp;quot;})
CREATE (ann:Person {name: &amp;quot;Ann&amp;quot;})
CREATE (xyz:Company {name: &amp;quot;XYZ&amp;quot;})
CREATE (x:Company {name: &amp;quot;Company X&amp;quot;})
CREATE (a:Company {name: &amp;quot;Company A&amp;quot;})
CREATE (Neo4j:Company {name: &amp;quot;Neo4j&amp;quot;})
CREATE (abc:Company {name: &amp;quot;ABC&amp;quot;})
CREATE (query:Technology {type: &amp;quot;Query Languages&amp;quot;})
CREATE (etl:Technology {type: &amp;quot;Data ETL&amp;quot;})
CREATE (integrations:Technology {type: &amp;quot;Integrations&amp;quot;})
CREATE (graphs:Technology {type: &amp;quot;Graphs&amp;quot;})
CREATE (dev:Technology {type: &amp;quot;Application Development&amp;quot;})
CREATE (java:Technology {type: &amp;quot;Java&amp;quot;})
CREATE (diana)-[:LIKES]-&amp;gt;(query)
CREATE (melissa)-[:LIKES]-&amp;gt;(query)
CREATE (dan)-[:LIKES]-&amp;gt;(etl)&amp;lt;-[:LIKES]-(melissa)
CREATE (xyz)&amp;lt;-[:WORKS_FOR]-(sally)-[:LIKES]-&amp;gt;(integrations)&amp;lt;-[:LIKES]-(dan)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(john)-[:LIKES]-&amp;gt;(java)
CREATE (john)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:LIKES]-&amp;gt;(java)
CREATE (john)-[:WORKS_FOR]-&amp;gt;(xyz)
CREATE (sally)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(melissa)
CREATE (joe)-[:LIKES]-&amp;gt;(query)
CREATE (x)&amp;lt;-[:WORKS_FOR]-(diana)&amp;lt;-[:IS_FRIENDS_WITH]-(joe)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(jennifer)-[:WORKS_FOR {startYear: 2017}]-&amp;gt;(Neo4j)
CREATE (ann)&amp;lt;-[:IS_FRIENDS_WITH]-(jennifer)-[:IS_FRIENDS_WITH]-&amp;gt;(mark)
CREATE (john)-[:LIKES]-&amp;gt;(dev)&amp;lt;-[:LIKES]-(ann)-[:IS_FRIENDS_WITH]-&amp;gt;(dan)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (ann)-[:WORKS_FOR]-&amp;gt;(abc)
CREATE (a)&amp;lt;-[:WORKS_FOR]-(melissa)-[:LIKES]-&amp;gt;(graphs)&amp;lt;-[:LIKES]-(diana)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假设您想知道谁拥有三到七年的经验。以下代码块显示了这种情况的 Cypher 查询。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)
WHERE 3 &amp;lt;= p.yearsExperience &amp;lt;= 7
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-filter-ranges-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher filter ranges arr&quot;&gt;&lt;/p&gt;
&lt;h2&gt;测试属性是否存在&lt;/h2&gt;
&lt;p&gt;您可能只对节点或关系上是否存在属性感兴趣。例如，您可能想检查系统中的哪些客户拥有 Twitter 句柄，以便您可以显示相关内容。或者，您可以检查您的所有员工是否都具有开始日期属性，以验证哪些实体可能需要更新。&lt;/p&gt;
&lt;p&gt;请记住：在 Neo4j 中，只有当属性具有值时，该属性才存在（存储）。不会存储空属性。这确保仅为您的节点和关系保留有价值的必要信息。&lt;/p&gt;
&lt;p&gt;要在 Neo4j v5 中编写这种类型的存在检查，您需要使用 &lt;code&gt;IS NOT NULL&lt;/code&gt; 谓词来仅包含属性存在的节点或关系。&lt;/p&gt;
&lt;p&gt;Cypher 代码写在下面的块中。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: find all users who have a twitter property
MATCH (p:Person)
WHERE p.twitter IS NOT NULL
RETURN p.name;

&amp;#x2F;&amp;#x2F;Query2: find all WORKS_FOR relationships that have a startYear property
MATCH (p:Person)-[rel:WORKS_FOR]-&amp;gt;(c:Company)
WHERE rel.startYear IS NOT NULL
RETURN p, rel, c;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 4

+------------------------+
| p.name                 |
+------------------------+
| &amp;#x27;Melissa&amp;#x27;              |
| &amp;#x27;Dan&amp;#x27;                  |
| &amp;#x27;Jennifer&amp;#x27;             |
| &amp;#x27;Mark&amp;#x27;                 |
+------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-filter-exists-relProp-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher filter exists relProp arr&quot;&gt;&lt;/p&gt;
&lt;h2&gt;检查字符串 - 部分值、模糊搜索&lt;/h2&gt;
&lt;p&gt;某些场景需要查询语法来匹配字符串中的部分值或广泛类别。要执行这种类型的查询，您需要一些灵活性以及用于字符串匹配和搜索的选项。无论您是寻找以某个值开头、结尾还是包含某个值的字符串，Cypher 都可以轻松且高效地处理它。&lt;/p&gt;
&lt;p&gt;Cypher 中有一些关键字与 &lt;code&gt;WHERE&lt;/code&gt; 子句一起使用来测试字符串属性值。&lt;code&gt;STARTS WITH&lt;/code&gt; 关键字允许您检查属性的值是否以您指定的字符串开头。使用 &lt;code&gt;CONTAINS&lt;/code&gt; 关键字，您可以检查指定的字符串是否是属性值的一部分。&lt;code&gt;ENDS_WITH&lt;/code&gt; 关键字检查属性字符串的末尾是否包含您指定的值。&lt;/p&gt;
&lt;p&gt;以下 Cypher 块中包含每个示例。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;check if a property starts with &amp;#x27;M&amp;#x27;
MATCH (p:Person)
WHERE p.name STARTS WITH &amp;#x27;M&amp;#x27;
RETURN p.name;

&amp;#x2F;&amp;#x2F;check if a property contains &amp;#x27;a&amp;#x27;
MATCH (p:Person)
WHERE p.name CONTAINS &amp;#x27;a&amp;#x27;
RETURN p.name;

&amp;#x2F;&amp;#x2F;check if a property ends with &amp;#x27;n&amp;#x27;
MATCH (p:Person)
WHERE p.name ENDS WITH &amp;#x27;n&amp;#x27;
RETURN p.name;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您还可以使用正则表达式来测试字符串的值。例如，您可以查找共享名字的所有 &lt;code&gt;Person&lt;/code&gt; 节点，或者您可以找到所有具有特定部门代码的类。&lt;/p&gt;
&lt;p&gt;让我们看一个例子。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)
WHERE p.name =~ &amp;#x27;Jo.*&amp;#x27;
RETURN p.name
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+--------------------------------+
| p.name                         |
+--------------------------------+
| &amp;#x27;John&amp;#x27;                         |
| &amp;#x27;Joe&amp;#x27;                          |
+--------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;就像在 SQL 和其他语言中一样，您可以检查属性值是否是列表中的值。&lt;code&gt;IN&lt;/code&gt; 关键字允许您指定一个值数组，并根据列表中的每个值验证属性的内容。&lt;/p&gt;
&lt;p&gt;这是一个例子：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)
WHERE p.yearsExperience IN [1, 5, 6]
RETURN p.name, p.yearsExperience
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+--------------+-----------------+
| p.name       | p.yearsExp      |
+--------------+-----------------+
| &amp;#x27;Jennifer&amp;#x27;   | 5               |
| &amp;#x27;Dan&amp;#x27;        | 6               |
| &amp;#x27;John&amp;#x27;       | 5               |
+--------------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;过滤模式&lt;/h2&gt;
&lt;p&gt;使图独一无二的一件事是它对关系的关注。就像您可以根据节点标签或属性过滤查询一样，您也可以根据关系或模式过滤结果。这允许您测试模式是否也具有某种关系或没有，或者是否存在另一种模式。&lt;/p&gt;
&lt;p&gt;以下 Cypher 代码显示了如何完成此操作。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: find which people are friends of someone who works for Neo4j
MATCH (p:Person)-[r:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WHERE exists((p)-[:WORKS_FOR]-&amp;gt;(:Company {name: &amp;#x27;Neo4j&amp;#x27;}))
RETURN p, r, friend;

&amp;#x2F;&amp;#x2F;Query2: find Jennifer&amp;#x27;s friends who do not work for a company
MATCH (p:Person)-[r:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WHERE p.name = &amp;#x27;Jennifer&amp;#x27;
AND NOT exists((friend)-[:WORKS_FOR]-&amp;gt;(:Company))
RETURN friend.name;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-filter-exists-ptrn-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher filter exists ptrn arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+--------------------------------+
| friend.name                    |
+--------------------------------+
| &amp;#x27;Mark&amp;#x27;                         |
+--------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;可选模式&lt;/h2&gt;
&lt;p&gt;在某些情况下，您可能想要从模式中检索结果，即使它们不匹配整个模式或所有条件。这就是 SQL 中外部联接的工作方式。在 Cypher 中，您可以使用 &lt;code&gt;OPTIONAL MATCH&lt;/code&gt; 模式尝试匹配它，但如果它没有找到结果，则这些行将为这些值返回 null。&lt;/p&gt;
&lt;p&gt;您可以通过查询名称以特定字母开头并且可能为公司工作的人员来查看这在 Cypher 中的外观。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Find all people whose name starts with J and who may work for a company.
MATCH (p:Person)
WHERE p.name STARTS WITH &amp;#x27;J&amp;#x27;
OPTIONAL MATCH (p)-[:WORKS_FOR]-(other:Company)
RETURN p.name, other.name;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+--------------------------------+
| p.name      | other.name       |
+--------------------------------+
| &amp;#x27;Jennifer&amp;#x27;  | &amp;#x27;Neo4j&amp;#x27;          |
| &amp;#x27;John&amp;#x27;      | &amp;#x27;XYZ&amp;#x27;            |
| &amp;#x27;Joe&amp;#x27;       | null             |
+--------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意，Joe 会被返回，因为他的名字以字母“J”开头，但他的公司名称为 null。那是因为他没有与 &lt;code&gt;COMPANY&lt;/code&gt; 节点的 &lt;code&gt;WORKS_FOR&lt;/code&gt; 关系。由于您使用了 &lt;code&gt;OPTIONAL MATCH&lt;/code&gt;，因此他的 &lt;code&gt;Person&lt;/code&gt; 节点仍然从第一个匹配项返回，但未找到第二个匹配项，因此返回 null。&lt;/p&gt;
&lt;p&gt;要查看差异，请尝试在第二个匹配项的前面运行没有 &lt;code&gt;OPTIONAL&lt;/code&gt; 的查询。您可以看到不再返回 Joe 的行。那是因为 Cypher 使用 &lt;code&gt;AND&lt;/code&gt; 匹配读取语句，因此该人必须匹配第一个条件（名称以“J”开头）和第二个条件（该人为公司工作）。&lt;/p&gt;
&lt;h2&gt;更复杂的模式&lt;/h2&gt;
&lt;p&gt;即使在这一点上，您也能够处理许多简单的图查询。但是，当您想要将模式扩展到单个关系之外时会发生什么？如果您想知道除了 Jennifer 之外还有谁喜欢图，该怎么办？&lt;/p&gt;
&lt;p&gt;我们通过简单地添加到我们的第一个模式或匹配其他模式来处理此功能和许多其他功能。让我们看几个例子。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: find who likes graphs besides Jennifer
MATCH (j:Person {name: &amp;#x27;Jennifer&amp;#x27;})-[r:LIKES]-(graph:Technology {type: &amp;#x27;Graphs&amp;#x27;})-[r2:LIKES]-(p:Person)
RETURN p.name;

&amp;#x2F;&amp;#x2F;Query2: find who likes graphs besides Jennifer that she is also friends with
MATCH (j:Person {name: &amp;#x27;Jennifer&amp;#x27;})-[:LIKES]-&amp;gt;(:Technology {type: &amp;#x27;Graphs&amp;#x27;})&amp;lt;-[:LIKES]-(p:Person),
      (j)-[:IS_FRIENDS_WITH]-(p)
RETURN p.name;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+-----------------------+
| p.name                |
+-----------------------+
| &amp;#x27;Diana&amp;#x27;               |
| &amp;#x27;Mark&amp;#x27;                |
| &amp;#x27;Melissa&amp;#x27;             |
+-----------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+-----------------------+
| p.name                |
+-----------------------+
| &amp;#x27;Mark&amp;#x27;                |
| &amp;#x27;Melissa&amp;#x27;             |
+-----------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意，在第二个查询中，在第一个 &lt;code&gt;MATCH&lt;/code&gt; 行之后使用逗号，并在下一行添加另一个模式以进行匹配。这允许您将模式链接在一起，类似于您上面使用的 &lt;code&gt;WHERE exists(&amp;lt;pattern&amp;gt;)&lt;/code&gt; 语法。使用此结构，您可以添加多个不同的模式并将它们链接在一起，从而允许您使用某些模式遍历图的各个部分。&lt;/p&gt;
&lt;h2&gt;返回结果&lt;/h2&gt;
&lt;p&gt;到目前为止，您已经通过它们的变量直接返回了节点、关系和路径。但是，&lt;code&gt;RETURN&lt;/code&gt; 子句可以返回任意数量的表达式。但是 Cypher 中的表达式是什么？&lt;/p&gt;
&lt;p&gt;最简单的表达式是文字值。文字值的示例包括：数字、字符串、数组（例如：&lt;code&gt;[1,2,3]&lt;/code&gt;）和映射（例如：&lt;code&gt;{name: &apos;Tom Hanks&apos;, born:1964, movies: [&apos;Forrest Gump&apos;, ...], count: 13}&lt;/code&gt;）。可以使用点语法访问任何节点、关系或映射的各个属性，例如：&lt;code&gt;n.name&lt;/code&gt;。可以使用下标检索数组的各个元素或切片，例如：&lt;code&gt;names[0]&lt;/code&gt; 和 &lt;code&gt;movies[1..-1]&lt;/code&gt;。每个函数评估，例如：&lt;code&gt;length(array)&lt;/code&gt;、&lt;code&gt;toInteger(&apos;12&apos;)&lt;/code&gt;、&lt;code&gt;substring(&apos;2014-07-01&apos;, 0, 4)&lt;/code&gt; 和 &lt;code&gt;coalesce(p.nickname, &apos;n/a&apos;)&lt;/code&gt; 也是一个表达式。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; 子句中使用的谓词计为布尔表达式。&lt;/p&gt;
&lt;p&gt;可以组合和连接简单表达式以形成更复杂的表达式。&lt;/p&gt;
&lt;p&gt;默认情况下，表达式本身用作列的标签，在许多情况下，您希望使用更易于理解的名称通过 &lt;code&gt;expression AS alias&lt;/code&gt; 为其设置别名。别名可以随后用于引用该列。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)
RETURN
  p,
  p.name AS name,
  toUpper(p.name),
  coalesce(p.nickname, &amp;#x27;n&amp;#x2F;a&amp;#x27;) AS nickname,
  {name: p.name, label: head(labels(p))} AS person
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+-------------------------------------------------------------------------------------------------------------------------------------------------+
| p                                               | name              | toUpper(p.name)   | nickname | person                                     |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| (:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;, born: 1964})    | &amp;#x27;Keanu Reeves&amp;#x27;    | &amp;#x27;KEANU REEVES&amp;#x27;    | &amp;#x27;n&amp;#x2F;a&amp;#x27;    | {name: &amp;#x27;Keanu Reeves&amp;#x27;, label: &amp;#x27;Person&amp;#x27;}    |
| (:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951}) | &amp;#x27;Robert Zemeckis&amp;#x27; | &amp;#x27;ROBERT ZEMECKIS&amp;#x27; | &amp;#x27;n&amp;#x2F;a&amp;#x27;    | {name: &amp;#x27;Robert Zemeckis&amp;#x27;, label: &amp;#x27;Person&amp;#x27;} |
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})       | &amp;#x27;Tom Hanks&amp;#x27;       | &amp;#x27;TOM HANKS&amp;#x27;       | &amp;#x27;n&amp;#x2F;a&amp;#x27;    | {name: &amp;#x27;Tom Hanks&amp;#x27;, label: &amp;#x27;Person&amp;#x27;}       |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您希望仅显示唯一结果，则可以在 &lt;code&gt;RETURN&lt;/code&gt; 之后使用 &lt;code&gt;DISTINCT&lt;/code&gt; 关键字：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (n)
RETURN DISTINCT labels(n) AS Labels
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+------------+
| Labels     |
+------------+
| [&amp;#x27;Movie&amp;#x27;]  |
| [&amp;#x27;Person&amp;#x27;] |
+------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;返回唯一结果&lt;/h2&gt;
&lt;p&gt;您可以使用 Cypher 中的 &lt;code&gt;DISTINCT&lt;/code&gt; 关键字返回唯一结果。由于节点的多个路径或满足多个条件的节点，您的某些查询可能会返回重复的结果。这种冗余会使结果混乱，并且难以筛选长列表以找到您需要的内容。&lt;/p&gt;
&lt;p&gt;要删除重复的实体，您可以使用 &lt;code&gt;DISTINCT&lt;/code&gt; 关键字。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query: find people who have a twitter and like graphs or query languages
MATCH (user:Person)
WHERE user.twitter IS NOT null
WITH user
MATCH (user)-[:LIKES]-(t:Technology)
WHERE t.type IN [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;]
RETURN DISTINCT user.name
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Query results:

Rows: 3

+-----------------------+
| user.name             |
+-----------------------+
| &amp;#x27;Jennifer&amp;#x27;            |
| &amp;#x27;Melissa&amp;#x27;             |
| &amp;#x27;Mark&amp;#x27;                |
+-----------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;对于前面的查询，用例是您正在为 Cypher 推出一个新的 Twitter 帐户，其中包含提示和技巧，并且您想要通知拥有 Twitter 帐户并且喜欢图或查询语言的用户。查询的前两行查找具有 Twitter 句柄的 &lt;code&gt;Person&lt;/code&gt; 节点。然后，您使用 &lt;code&gt;WITH&lt;/code&gt; 将这些用户传递到下一个 &lt;code&gt;MATCH&lt;/code&gt;，您可以在其中找出该人是否喜欢图或查询语言。请注意，在没有 &lt;code&gt;DISTINCT&lt;/code&gt; 关键字的情况下运行此语句会导致“Melissa”显示两次。这是因为她喜欢图，而且她也喜欢查询语言。当使用 &lt;code&gt;DISTINCT&lt;/code&gt; 时，您只会检索唯一用户。&lt;/p&gt;
&lt;h2&gt;限制结果数&lt;/h2&gt;
&lt;p&gt;有时您想要一个抽样集，或者您只想一次提取这么多结果来更新或处理。&lt;code&gt;LIMIT&lt;/code&gt; 关键字获取查询的输出，并根据您指定的数字限制返回的卷。&lt;/p&gt;
&lt;p&gt;例如，您可以找到图中每个人的朋友数。如果该图有成千上万或数百万个节点和关系，则返回的结果数将是巨大的。如果您只关心拥有最多朋友的前三个人怎么办？让我们为此编写一个查询！&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query: find the top 3 people who have the most friends
MATCH (p:Person)-[r:IS_FRIENDS_WITH]-(other:Person)
RETURN p.name, count(other.name) AS numberOfFriends
ORDER BY numberOfFriends DESC
LIMIT 3
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+--------------------------------+
| p.name      | numberOfFriends  |
+--------------------------------+
| &amp;#x27;Jennifer&amp;#x27;  | 5                |
| &amp;#x27;Mark&amp;#x27;      | 2                |
| &amp;#x27;Ann&amp;#x27;       | 2                |
+--------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;该查询提取人员以及他们连接的朋友，并返回人员姓名和他们的朋友的计数。您可以只运行查询的那么多内容并返回名称和朋友计数的混乱列表，但您可能想要根据每个人拥有的朋友数量（从顶部最大的数字开始 (DESC)）对列表进行排序。您也可以运行查询的那么多内容以查看所有排序的朋友和计数，但在上面的示例中，已从图中提取了拥有最多朋友的前三个人。&lt;code&gt;LIMIT&lt;/code&gt; 从排序列表中提取顶部结果。&lt;/p&gt;
&lt;p&gt;尝试通过删除 &lt;code&gt;ORDER BY&lt;/code&gt; 和 &lt;code&gt;LIMIT&lt;/code&gt; 行来混合查询，然后分别添加每一行。请注意，仅删除 &lt;code&gt;ORDER BY&lt;/code&gt; 行会从列表中提取起始三个值，从而获得返回结果的随机抽样。&lt;/p&gt;
&lt;h2&gt;聚合信息&lt;/h2&gt;
&lt;p&gt;在许多情况下，我们希望在遍历图中的模式时聚合或分组遇到的数据。在 Cypher 中，聚合发生在 &lt;code&gt;RETURN&lt;/code&gt; 子句中，同时计算最终结果。支持许多常见的聚合函数，例如 &lt;code&gt;count&lt;/code&gt;、&lt;code&gt;sum&lt;/code&gt;、&lt;code&gt;avg&lt;/code&gt;、&lt;code&gt;min&lt;/code&gt; 和 &lt;code&gt;max&lt;/code&gt;，但还有更多。&lt;/p&gt;
&lt;p&gt;可以通过以下方式实现计算电影数据库中的人数：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Person)
RETURN count(*) AS people
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+--------+
| people |
+--------+
| 3      |
+--------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果要跳过空值，请使用函数 &lt;code&gt;count(variable)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;要仅聚合唯一值，请使用 &lt;code&gt;DISTINCT&lt;/code&gt; 运算符，例如：&lt;code&gt;count(DISTINCT role)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;聚合在 Cypher 中隐式工作。您指定要聚合的结果列。Cypher 使用所有非聚合列作为分组键。&lt;/p&gt;
&lt;p&gt;聚合会影响在排序或后续查询部分中仍然可见的数据。&lt;/p&gt;
&lt;p&gt;以下语句找出演员和导演一起工作的频率：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (actor:Person)-[:ACTED_IN]-&amp;gt;(movie:Movie)&amp;lt;-[:DIRECTED]-(director:Person)
RETURN actor, director, count(*) AS collaborations
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+--------------------------------------------------------------------------------------------------------------+
| actor                                     | director                                        | collaborations |
+--------------------------------------------------------------------------------------------------------------+
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956}) | (:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951}) | 1              |
+--------------------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;有三种不同的方法可以使用 &lt;code&gt;count()&lt;/code&gt; 函数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;count(*)&lt;/code&gt;：计算结果并返回匹配行数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count(n)&lt;/code&gt;：计算 &lt;code&gt;n&lt;/code&gt; 的出现次数（排除空值）。您可以指定节点、关系或属性，供 Cypher 计数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count(DISTINCT variable)&lt;/code&gt;：&lt;code&gt;DISTINCT&lt;/code&gt; 运算符从结果中删除重复项。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在数据集“人员、技术和公司”中，某些 &lt;code&gt;Person&lt;/code&gt; 节点具有 Twitter 句柄，而另一些则没有。如果您运行下面的第一个示例查询，您将看到 &lt;code&gt;twitter&lt;/code&gt; 属性对四个人有一个值，而对其他五个人则为 null。第二个和第三个查询显示了如何使用不同的计数选项。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: see the list of Twitter handle values for Person nodes
MATCH (p:Person)
RETURN p.twitter;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 9

+--------------+
| p.twitter    |
+--------------+
| &amp;#x27;@jennifer&amp;#x27;  |
| &amp;#x27;@melissa&amp;#x27;   |
| null         |
| &amp;#x27;@mark&amp;#x27;      |
| &amp;#x27;@dan&amp;#x27;       |
| null         |
| null         |
| null         |
| null         |
+--------------+
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query2: count of the non-null &amp;#96;twitter&amp;#96; property of the Person nodes
MATCH (p:Person)
RETURN count(p.twitter);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+-------------------+
| count(p.twitter)  |
+-------------------+
| 4                 |
+-------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query3: count on the Person nodes
MATCH (p:Person)
RETURN count(*);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query3 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+-------------------+
| count(*)          |
+-------------------+
| 9                 |
+-------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;收集聚合&lt;/h2&gt;
&lt;p&gt;一个非常有用的聚合函数是 &lt;code&gt;collect(expression)&lt;/code&gt;，它返回由表达式返回的值的单个聚合列表。这在许多情况下非常有用，因为在聚合时不会丢失任何详细信息。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;collect()&lt;/code&gt; 非常适合检索典型的父子结构，其中每行返回一个核心实体（父级、根或头），所有依赖信息都在使用 &lt;code&gt;collect()&lt;/code&gt; 创建的关联列表中。这意味着无需为每个子行重复父信息，也无需运行 n+1 个语句来单独检索父及其子项。&lt;/p&gt;
&lt;p&gt;以下语句可用于检索数据库中每部电影的演员阵容：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)&amp;lt;-[:ACTED_IN]-(a:Person)
RETURN m.title AS movie, collect(a.name) AS cast, count(*) AS actors
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+-----------------------------------------+
| movie          | cast          | actors |
+-----------------------------------------+
| &amp;#x27;Forrest Gump&amp;#x27; | [&amp;#x27;Tom Hanks&amp;#x27;] | 1      |
| &amp;#x27;Cloud Atlas&amp;#x27;  | [&amp;#x27;Tom Hanks&amp;#x27;] | 1      |
+-----------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;由 &lt;code&gt;collect()&lt;/code&gt; 创建的列表可以从使用 Cypher 结果的客户端使用，也可以直接在具有任何列表函数或谓词的语句中使用。&lt;/p&gt;
&lt;h2&gt;循环遍历列表值&lt;/h2&gt;
&lt;p&gt;如果您有一个想要检查或分离值的列表，Cypher 提供了 &lt;code&gt;UNWIND&lt;/code&gt; 子句。这与 &lt;code&gt;collect()&lt;/code&gt; 的作用相反，并将列表分离为单独行上的各个值。&lt;/p&gt;
&lt;p&gt;在导入数据以及日常数组和其他类型的列表时，&lt;code&gt;UNWIND&lt;/code&gt; 经常用于循环遍历 JSON 和 XML 对象。让我们看几个示例，我们假设某人喜欢的技术也意味着他们对每项技术都有一些经验。如果您有兴趣雇用熟悉图或查询语言的人员，您可以编写以下查询来查找要面试的人员。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: for a list of techRequirements, look for people who have each skill
WITH [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;] AS techRequirements
UNWIND techRequirements AS technology
MATCH (p:Person)-[r:LIKES]-(t:Technology {type: technology})
RETURN t.type, collect(p.name) AS potentialCandidates;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+-------------------+------------------------------------------+
| t.type            | potentialCandidates                      |
+-------------------+------------------------------------------+
| &amp;#x27;Graphs&amp;#x27;          | [&amp;#x27;Diana&amp;#x27;, &amp;#x27;Mark&amp;#x27;, &amp;#x27;Melissa&amp;#x27;, &amp;#x27;Jennifer&amp;#x27;] |
| &amp;#x27;Query Languages&amp;#x27; | [&amp;#x27;Diana&amp;#x27;, &amp;#x27;Melissa&amp;#x27;, &amp;#x27;Joe&amp;#x27;]              |
+-------------------+------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query2: for numbers in a list, find candidates who have that many years of experience
WITH [4, 5, 6, 7] AS experienceRange
UNWIND experienceRange AS number
MATCH (p:Person)
WHERE p.yearsExp = number
RETURN p.name, p.yearsExp;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 4

+--------------+-----------------+
| p.name       | p.yearsExp      |
+--------------+-----------------+
| &amp;#x27;Sally&amp;#x27;      | 4               |
| &amp;#x27;Jennifer&amp;#x27;   | 5               |
| &amp;#x27;John&amp;#x27;       | 5               |
| &amp;#x27;Dan&amp;#x27;        | 6               |
+--------------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;排序和分页&lt;/h2&gt;
&lt;p&gt;通常在使用 &lt;code&gt;count(x)&lt;/code&gt; 聚合后进行排序和分页。&lt;/p&gt;
&lt;p&gt;排序是使用 &lt;code&gt;ORDER BY expression [ASC|DESC]&lt;/code&gt; 子句完成的。该表达式可以是任何表达式，只要它可以从返回的信息中计算出来。&lt;/p&gt;
&lt;p&gt;例如，如果您返回 &lt;code&gt;person.name&lt;/code&gt;，您仍然可以 &lt;code&gt;ORDER BY person.age&lt;/code&gt;，因为两者都可以从 &lt;code&gt;person&lt;/code&gt; 引用访问。您不能按未返回的内容排序。这对于聚合和 &lt;code&gt;DISTINCT&lt;/code&gt; 返回值尤其重要，因为两者都会删除聚合数据的可见性。&lt;/p&gt;
&lt;p&gt;分页是使用 &lt;code&gt;SKIP {offset}&lt;/code&gt; 和 &lt;code&gt;LIMIT {count}&lt;/code&gt; 子句完成的。&lt;/p&gt;
&lt;p&gt;一个常见的模式是聚合计数（分数或频率），按其排序，并且仅返回前 n 个条目。&lt;/p&gt;
&lt;p&gt;例如，要找到最多产的演员，您可以这样做：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (a:Person)-[:ACTED_IN]-&amp;gt;(m:Movie)
RETURN a, count(*) AS appearances
ORDER BY appearances DESC LIMIT 10
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+---------------------------------------------------------+
| a                                         | appearances |
+---------------------------------------------------------+
| (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956}) | 2           |
+---------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;排序结果&lt;/h2&gt;
&lt;p&gt;如果您可以按最多或最少的经验对我们先前示例中的潜在招聘候选人列表进行排序，那么它可能会更有用。或者，您可能想要按年龄对我们所有的人员进行排名。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ORDER BY&lt;/code&gt; 关键字根据您在升序或降序中指定的值对结果进行排序（升序是默认值）。让我们使用与 &lt;code&gt;UNWIND&lt;/code&gt; 相同的示例查询，看看如何对候选人进行排序。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: for a list of techRequirements, look for people who have each skill
WITH [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;] AS techRequirements
UNWIND techRequirements AS technology
MATCH (p:Person)-[r:LIKES]-(t:Technology {type: technology})
WITH t.type AS technology, p.name AS personName
ORDER BY technology, personName
RETURN technology, collect(personName) AS potentialCandidates;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 2

+-------------------+------------------------------------------+
| technology        | potentialCandidates                      |
+-------------------+------------------------------------------+
| &amp;#x27;Graphs&amp;#x27;          | [&amp;#x27;Diana&amp;#x27;, &amp;#x27;Jennifer&amp;#x27;, &amp;#x27;Mark&amp;#x27;, &amp;#x27;Melissa&amp;#x27;] |
| &amp;#x27;Query Languages&amp;#x27; | [&amp;#x27;Diana&amp;#x27;, &amp;#x27;Joe&amp;#x27;]                           |
+-------------------+------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query2: for numbers in a list, find candidates who have that many years of experience
WITH [4, 5, 6, 7] AS experienceRange
UNWIND experienceRange AS number
MATCH (p:Person)
WHERE p.yearsExp = number
RETURN p.name, p.yearsExp ORDER BY p.yearsExp DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 4

+--------------+-----------------+
| p.name       | p.yearsExp      |
+--------------+-----------------+
| &amp;#x27;Dan&amp;#x27;        | 6               |
| &amp;#x27;Jennifer&amp;#x27;   | 5               |
| &amp;#x27;John&amp;#x27;       | 5               |
| &amp;#x27;Sally&amp;#x27;      | 4               |
+--------------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意，第一个查询必须先按人员姓名排序，然后才能将值收集到列表中。如果您不先排序（将 &lt;code&gt;ORDER BY&lt;/code&gt; 放在 &lt;code&gt;RETURN&lt;/code&gt; 子句之后），您将根据列表的大小而不是列表中值的首字母进行排序。结果也被排序为两个值：技术，然后是人。这允许您对技术进行排序，以便将喜欢某项技术的所有人员列在一起。&lt;/p&gt;
&lt;p&gt;您可以通过运行以下查询来尝试按两个值或一个值进行排序的差异：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;only sorted by person&amp;#x27;s name in alphabetical order
WITH [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;] AS techRequirements
UNWIND techRequirements AS technology
MATCH (p:Person)-[r:LIKES]-(t:Technology {type: technology})
WITH t.type AS technology, p.name AS personName
ORDER BY personName
RETURN technology, personName;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;only sorted by technology (person names are out of order)
WITH [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;] AS techRequirements
UNWIND techRequirements AS technology
MATCH (p:Person)-[r:LIKES]-(t:Technology {type: technology})
WITH t.type AS technology, p.name AS personName
ORDER BY technology
RETURN technology, personName;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;sorted by technology, then by person&amp;#x27;s name
WITH [&amp;#x27;Graphs&amp;#x27;,&amp;#x27;Query Languages&amp;#x27;] AS techRequirements
UNWIND techRequirements AS technology
MATCH (p:Person)-[r:LIKES]-(t:Technology {type: technology})
WITH t.type AS technology, p.name AS personName
ORDER BY technology, personName
RETURN technology, personName;
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;计算列表中的值&lt;/h2&gt;
&lt;p&gt;如果您有一个值列表，您还可以使用 &lt;code&gt;size()&lt;/code&gt; 函数查找该列表中的项目数或计算表达式的大小。以下示例返回找到的项目数。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query1: find number of items in collected list
MATCH (p:Person)-[:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
RETURN p.name, size(collect(friend.name)) AS numberOfFriends;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query1 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 4

+--------------+-----------------+
| p.name       | numberOfFriends |
+--------------+-----------------+
| &amp;#x27;John&amp;#x27;       | 1               |
| &amp;#x27;Jennifer&amp;#x27;   | 5               |
| &amp;#x27;Ann&amp;#x27;        | 1               |
| &amp;#x27;Joe&amp;#x27;        | 2               |
+--------------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在 Neo4j v5 中，如果您需要查找关系模式的数量，请使用 &lt;code&gt;COUNT {}&lt;/code&gt; 表达式。请看以下 Cypher 查询示例。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F;Query2: find number of friends who have other friends
MATCH (p:Person)-[:IS_FRIENDS_WITH]-&amp;gt;(friend:Person)
WHERE count{(friend)-[:IS_FRIENDS_WITH]-(:Person)} &amp;gt; 1
RETURN p.name, collect(friend.name) AS friends, count{(friend)-[:IS_FRIENDS_WITH]-(:Person)} AS numberOfFoFs;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Query2 结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 3

+--------------+----------------------------------+---------------+
| p.name       | friends                          | numberOfFoFs  |
+--------------+----------------------------------+---------------+
| &amp;#x27;Joe&amp;#x27;        | [&amp;#x27;Mark&amp;#x27;]                         | 2             |
| &amp;#x27;Jennifer&amp;#x27;   | [&amp;#x27;Mark&amp;#x27;, &amp;#x27;John&amp;#x27;, &amp;#x27;Sally&amp;#x27;, &amp;#x27;Ann&amp;#x27;] | 2             |
| &amp;#x27;John&amp;#x27;       | [&amp;#x27;Sally&amp;#x27;]                        | 2             |
+--------------+----------------------------------+---------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;资源&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neo4j Cypher 手册：WITH、UNWIND 等&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：聚合&lt;/li&gt;
&lt;li&gt;Neo4j Cypher 手册：size()&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Wed, 09 Apr 2025 02:28:30 GMT</pubDate></item><item><title>Neo4j官方教程：第9节，实践中的模式</title><link>http://neo4j.com.cn/topic/67f5d4a0455186f56d9f4134</link><guid>http://neo4j.com.cn/topic/67f5d4a0455186f56d9f4134</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/patterns-in-practice/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/patterns-in-practice/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;实践中的模式&lt;/h1&gt;
&lt;h2&gt;创建和返回数据&lt;/h2&gt;
&lt;p&gt;让我们首先看看允许您创建数据的子句。&lt;/p&gt;
&lt;p&gt;要添加数据，您只需使用您已经知道的模式。通过提供模式，您可以指定哪些图结构、标签和属性要成为图的一部分。&lt;/p&gt;
&lt;p&gt;显然，最简单的子句称为 &lt;code&gt;CREATE&lt;/code&gt;。它创建您指定的模式。&lt;/p&gt;
&lt;p&gt;对于您到目前为止所看到的模式，这可能如下所示：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Movie {title: &amp;#x27;The Matrix&amp;#x27;, released: 1997})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果您运行此语句，Cypher® 将返回更改的数量：在本例中，添加一个节点、一个标签和两个属性。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;由于您从一个空数据库开始，因此您现在有一个数据库，其中包含一个节点：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice01-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice01 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果您还想返回创建的数据，您可以添加一个 &lt;code&gt;RETURN&lt;/code&gt; 子句，该子句引用您已分配给模式元素的变量。
Cypher 中的 &lt;code&gt;RETURN&lt;/code&gt; 关键字指定您可能希望从 Cypher 查询返回的值或结果。
您可以告诉 Cypher 返回节点、关系、节点和关系属性或查询结果中的模式。
执行写入过程时不需要 &lt;code&gt;RETURN&lt;/code&gt;，但读取时需要。
当使用 &lt;code&gt;RETURN&lt;/code&gt; 时，前面讨论的节点和关系变量变得很重要。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (p:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;, born: 1964})
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是返回的内容：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 1

+----------------------------------------------+
| p                                            |
+----------------------------------------------+
| (:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;, born: 1964}) |
+----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果要创建多个元素，可以用逗号分隔元素或使用多个 &lt;code&gt;CREATE&lt;/code&gt; 语句。&lt;/p&gt;
&lt;p&gt;当然，您还可以创建更复杂的结构，例如包含有关角色的信息的 &lt;code&gt;ACTED_IN&lt;/code&gt; 关系，或导演的 &lt;code&gt;DIRECTED&lt;/code&gt; 关系。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (a:Person {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})-[r:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;]}]-&amp;gt;(m:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994})
CREATE (d:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951})-[:DIRECTED]-&amp;gt;(m)
RETURN a, d, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是更新后的图的一部分：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice02-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice02 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;在大多数情况下，您希望将新数据添加到现有结构。这需要知道如何在图数据中查找现有模式，这将在下一节中介绍。&lt;/p&gt;
&lt;h2&gt;匹配模式&lt;/h2&gt;
&lt;p&gt;匹配模式是 &lt;code&gt;MATCH&lt;/code&gt; 语句的任务。您将到目前为止使用的相同类型的模式传递给 &lt;code&gt;MATCH&lt;/code&gt;，以描述您要查找的内容。它类似于按示例查询，只是您的示例还包括结构。要返回节点、关系、属性或模式，您需要在 &lt;code&gt;MATCH&lt;/code&gt; 子句中为要返回的数据指定变量。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MATCH&lt;/code&gt; 语句搜索您指定的模式，并为每个成功的模式匹配返回一行。&lt;/p&gt;
&lt;p&gt;要查找您到目前为止创建的数据，您可以开始查找所有带有 &lt;code&gt;Movie&lt;/code&gt; 标签的节点。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie)
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果如下：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice03-arr.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src alt=&quot;cypher intro patterns in practice03 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;这应该显示《黑客帝国》和《阿甘正传》。&lt;/p&gt;
&lt;p&gt;您还可以查找特定的人，例如基努·里维斯。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Keanu Reeves&amp;#x27;})
RETURN p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此查询返回匹配的节点：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice04-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice04 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;请注意，您只提供足够的信息来查找节点，并非所有属性都是必需的。在大多数情况下，您都有关键属性，例如 SSN、ISBN、电子邮件、登录名、地理位置或产品代码来查找。&lt;/p&gt;
&lt;p&gt;您还可以找到更有趣的连接，例如，汤姆·汉克斯出演的电影的标题和他扮演的角色。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})-[r:ACTED_IN]-&amp;gt;(m:Movie)
RETURN m.title, r.roles
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Rows: 1

+------------------------------+
| m.title        | r.roles     |
+------------------------------+
| &amp;#x27;Forrest Gump&amp;#x27; | [&amp;#x27;Forrest&amp;#x27;] |
+------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在本例中，您只返回了您感兴趣的节点和关系的属性。您可以通过点表示法 &lt;code&gt;identifier.property&lt;/code&gt; 在任何地方访问它们。&lt;/p&gt;
&lt;p&gt;当然，这只列出了汤姆·汉克斯在《阿甘正传》中扮演的 Forrest 角色，因为这就是您添加的所有数据。&lt;/p&gt;
&lt;p&gt;现在您已经知道足够多的知识来将新节点添加到现有节点，并且可以将 &lt;code&gt;MATCH&lt;/code&gt; 和 &lt;code&gt;CREATE&lt;/code&gt; 组合起来以将结构附加到图中。&lt;/p&gt;
&lt;h2&gt;Cypher 示例&lt;/h2&gt;
&lt;p&gt;让我们看一些使用 &lt;code&gt;MATCH&lt;/code&gt; 和 &lt;code&gt;RETURN&lt;/code&gt; 关键字的示例。每个后续示例都比前一个示例更复杂。最后两个示例首先解释了我们试图实现的目标。如果您单击每个 Cypher 代码段下方的“运行查询”按钮，您可以在图或表的格式中查看结果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 1&lt;/strong&gt;：查找图中带有标签 &lt;code&gt;Person&lt;/code&gt; 的节点。请注意，如果要检索 &lt;code&gt;RETURN&lt;/code&gt; 子句中的节点，则必须为 &lt;code&gt;Person&lt;/code&gt; 节点使用一个变量，例如 &lt;code&gt;p&lt;/code&gt;。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)
RETURN p
LIMIT 1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 2&lt;/strong&gt;：查找图中名称为“Tom Hanks”的 &lt;code&gt;Person&lt;/code&gt; 节点。请记住，您可以随意命名您的变量，只要您稍后引用相同的名称即可。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (tom:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})
RETURN tom
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 3&lt;/strong&gt;：查找汤姆·汉克斯导演的电影。&lt;/p&gt;
&lt;p&gt;说明：首先，您应该找到汤姆·汉克斯的 &lt;code&gt;Person&lt;/code&gt; 节点，然后找到他连接到的 &lt;code&gt;Movie&lt;/code&gt; 节点。为此，您必须从汤姆·汉克斯的 &lt;code&gt;Person&lt;/code&gt; 节点到 &lt;code&gt;Movie&lt;/code&gt; 节点遵循 &lt;code&gt;DIRECTED&lt;/code&gt; 关系。您还指定了 &lt;code&gt;Movie&lt;/code&gt; 的标签，以便查询仅查看带有该标签的节点。由于您只关心在此查询中返回电影，因此您需要为该节点提供一个变量（&lt;code&gt;movie&lt;/code&gt;），但不需要为 &lt;code&gt;Person&lt;/code&gt; 节点或 &lt;code&gt;DIRECTED&lt;/code&gt; 关系提供变量。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})-[:DIRECTED]-&amp;gt;(movie:Movie)
RETURN movie
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 4&lt;/strong&gt;：查找汤姆·汉克斯导演的电影，但这次只返回电影的标题。&lt;/p&gt;
&lt;p&gt;说明：此查询与上一个查询类似。示例 3 返回了整个 &lt;code&gt;Movie&lt;/code&gt; 节点及其所有属性。对于此示例，您仍然需要找到汤姆的电影，但现在您只关心它们的标题。您应该使用语法 &lt;code&gt;variable.property&lt;/code&gt; 访问节点的 &lt;code&gt;title&lt;/code&gt; 属性以返回名称值。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})-[:DIRECTED]-&amp;gt;(movie:Movie)
RETURN movie.title
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;别名返回值&lt;/h2&gt;
&lt;p&gt;并非所有属性都像上面示例中的 &lt;code&gt;movie.title&lt;/code&gt; 那样简单。由于属性长度、多字描述、开发人员术语和其他快捷方式，某些属性的名称很差。这些命名约定可能难以阅读，尤其是在报告和其他面向用户的界面上。&lt;/p&gt;
&lt;h3&gt;命名不佳的属性&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F; 命名不佳的属性
MATCH (tom:Person {name:&amp;#x27;Tom Hanks&amp;#x27;})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name, tom.born, movie.title, movie.released
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;就像 SQL 一样，您可以使用 &lt;code&gt;AS&lt;/code&gt; 关键字重命名返回结果，并使用更清晰的名称为属性设置别名。&lt;/p&gt;
&lt;h3&gt;使用别名获得更清晰的结果&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F; 使用别名获得更清晰的打印结果
MATCH (tom:Person {name:&amp;#x27;Tom Hanks&amp;#x27;})-[rel:DIRECTED]-(movie:Movie)
RETURN tom.name AS name, tom.born AS &amp;#96;Year Born&amp;#96;, movie.title AS title, movie.released AS &amp;#96;Year Released&amp;#96;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以通过在别名前后使用反引号字符来指定包含空格的返回别名（&lt;code&gt;movie.released AS Year Released&lt;/code&gt;）。如果您没有包含空格的别名，则无需使用反引号。&lt;/p&gt;
&lt;h2&gt;附加结构&lt;/h2&gt;
&lt;p&gt;要使用新信息扩展图，首先要匹配现有的连接点，然后使用关系将新创建的节点附加到它们。像这样可以为汤姆·汉克斯添加一部新电影《云图》：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})
CREATE (m:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012})
CREATE (p)-[r:ACTED_IN {roles: [&amp;#x27;Zachry&amp;#x27;]}]-&amp;gt;(m)
RETURN p, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是数据库中的结构：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice05-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice05 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;重要的是要记住，您可以为节点和关系分配变量，并在以后使用它们，无论它们是创建的还是匹配的。&lt;/p&gt;
&lt;p&gt;可以在单个 &lt;code&gt;CREATE&lt;/code&gt; 子句中附加节点和关系。但是，为了提高可读性，将它们分开是有帮助的。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MATCH&lt;/code&gt; 和 &lt;code&gt;CREATE&lt;/code&gt; 组合的一个棘手方面是，每个匹配的模式都会得到一行。这会导致后续的 &lt;code&gt;CREATE&lt;/code&gt; 语句为每一行执行一次。在许多情况下，这正是您想要的。如果不是有意的，请将 &lt;code&gt;CREATE&lt;/code&gt; 语句移动到 &lt;code&gt;MATCH&lt;/code&gt; 之前，或者使用稍后讨论的方法更改查询的基数，或者使用下一个子句的获取或创建语义：&lt;code&gt;MERGE&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;完成模式&lt;/h2&gt;
&lt;p&gt;每当您从外部系统获取数据或不确定某些信息是否已存在于图中时，您都希望能够表达可重复（幂等）的更新操作。在 Cypher 中，&lt;code&gt;MERGE&lt;/code&gt; 子句具有此功能。它的作用类似于 &lt;code&gt;MATCH&lt;/code&gt; 或 &lt;code&gt;CREATE&lt;/code&gt; 的组合，它在创建数据之前检查数据是否存在。使用 &lt;code&gt;MERGE&lt;/code&gt;，您可以定义要查找或创建的模式。通常，与 &lt;code&gt;MATCH&lt;/code&gt; 一样，您只想在核心模式中包含要查找的关键属性。&lt;code&gt;MERGE&lt;/code&gt; 允许您提供要在 &lt;code&gt;ON CREATE&lt;/code&gt; 上设置的其他属性。&lt;/p&gt;
&lt;p&gt;如果您不知道您的图是否已经包含《云图》，您可以再次合并它。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MERGE (m:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;})
ON CREATE SET m.released = 2012
RETURN m
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;Created Nodes: 1
Added Labels: 1
Set Properties: 2
Rows: 1

+-------------------------------------------------+
| m                                               |
+-------------------------------------------------+
| (:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;, released: 2012}) |
+-------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在这两种情况下，您都会得到一个结果：要么是图中已经存在的数据（可能不止一行），要么是一个新创建的 &lt;code&gt;Movie&lt;/code&gt; 节点。&lt;/p&gt;
&lt;p&gt;没有任何先前分配变量的 &lt;code&gt;MERGE&lt;/code&gt; 子句要么匹配完整模式，要么创建完整模式。它永远不会产生模式中匹配和创建的部分混合。要实现部分匹配/创建，请确保对不应受影响的部分使用已定义的变量。&lt;/p&gt;
&lt;p&gt;因此，最重要的是，&lt;code&gt;MERGE&lt;/code&gt; 确保您不能创建重复的信息或结构，但它需要首先检查现有匹配项的成本。尤其是在大型图上，扫描一组带有标签的节点以查找特定属性可能代价高昂。您可以通过创建支持索引或约束来缓解这种情况，这将在后面的章节中讨论。但这仍然不是免费的，因此，只要您确定不会创建重复数据，请使用 &lt;code&gt;CREATE&lt;/code&gt; 而不是 &lt;code&gt;MERGE&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MERGE&lt;/code&gt; 还可以断言仅创建一次关系。为此，您必须从先前的模式匹配中传入两个节点。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (m:Movie {title: &amp;#x27;Cloud Atlas&amp;#x27;})
MATCH (p:Person {name: &amp;#x27;Tom Hanks&amp;#x27;})
MERGE (p)-[r:ACTED_IN]-&amp;gt;(m)
ON CREATE SET r.roles =[&amp;#x27;Zachry&amp;#x27;]
RETURN p, r, m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice06-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice06 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果关系的方向是任意的，您可以省略箭头。&lt;code&gt;MERGE&lt;/code&gt; 检查任一方向的关系，如果没有匹配的关系，则创建一个新的有向关系。&lt;/p&gt;
&lt;p&gt;如果您选择仅从前面的子句中传入一个节点，则 &lt;code&gt;MERGE&lt;/code&gt; 提供了一个有趣的功能。它仅在给定模式的提供的节点的直接邻域内匹配，如果未找到该模式，则创建它。这对于创建树结构非常有用。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (y:Year {year: 2014})
MERGE (y)&amp;lt;-[:IN_YEAR]-(m10:Month {month: 10})
MERGE (y)&amp;lt;-[:IN_YEAR]-(m11:Month {month: 11})
RETURN y, m10, m11
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是创建的图结构：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-intro-patterns-in-practice07-arr.svg&quot; alt=&quot;image&quot;&gt;
&lt;img src alt=&quot;cypher intro patterns in practice07 arr&quot;&gt;&lt;/p&gt;
&lt;p&gt;这里没有对两个 &lt;code&gt;Month&lt;/code&gt; 节点进行全局搜索；仅在 2014 &lt;code&gt;Year&lt;/code&gt; 节点的上下文中搜索它们。&lt;/p&gt;
&lt;h2&gt;代码挑战&lt;/h2&gt;
&lt;p&gt;现在了解了基础知识，请使用下面的部分构建一个 Cypher 语句，以查找汤姆·汉克斯 &lt;code&gt;DIRECTED&lt;/code&gt; 的每个 &lt;code&gt;Movie&lt;/code&gt; 的标题和发行年份。单击这些部分以按顺序添加它们，完成后，单击“运行查询”以查看您是否正确。您可以单击代码块内的任何查询部分以将其删除。&lt;/p&gt;
&lt;p&gt;从下面的选项中选择以完成查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;{name:})-[:MovieRETURNPerson&amp;quot;Tom Hanks&amp;quot;)m.title, m.released]-&amp;gt;(m:DIRECTED(p:MATCH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Wed, 09 Apr 2025 02:00:00 GMT</pubDate></item><item><title>Neo4j官方教程：第8节， 模式</title><link>http://neo4j.com.cn/topic/67f5cf0f455186f56d9f4133</link><guid>http://neo4j.com.cn/topic/67f5cf0f455186f56d9f4133</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher/&quot;&gt;https://neo4j.com/docs/getting-started/cypher/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;模式&lt;/h1&gt;
&lt;p&gt;Neo4j 的属性图由节点和关系组成，它们都可以具有属性。节点表示实体，例如概念、事件、地点和事物。关系连接成对的节点。&lt;/p&gt;
&lt;p&gt;但是，节点和关系可以被认为是低级构建块。属性图的真正优势在于它能够编码连接的节点和关系的模式。单个节点或关系通常编码的信息很少，但是节点和关系的模式可以编码任意复杂的想法。&lt;/p&gt;
&lt;p&gt;Cypher®（Neo4j 的查询语言）强烈基于模式。具体来说，模式用于匹配所需的图结构。一旦找到或创建了匹配的结构，Neo4j 就可以使用它进行进一步处理。&lt;/p&gt;
&lt;p&gt;一个简单的模式（只有一个关系）连接一对节点（或者，偶尔，一个节点连接到自身）。例如，一个人 &lt;code&gt;LIVES_IN&lt;/code&gt; 一个城市，或者一个城市是 &lt;code&gt;PART_OF&lt;/code&gt; 一个国家。&lt;/p&gt;
&lt;p&gt;使用多个关系的复杂模式可以表达任意复杂的概念，并支持各种有趣的用例。例如，我们可能想要匹配一个人 &lt;code&gt;LIVES_IN&lt;/code&gt; 一个国家的实例。以下 Cypher 代码将两个简单的模式组合成一个稍微复杂的模式，该模式执行此匹配：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(:Person) -[:LIVES_IN]-&amp;gt; (:City) -[:PART_OF]-&amp;gt; (:Country)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;由图标和箭头组成的图通常用于可视化图。文本注释提供标签，定义属性等。&lt;/p&gt;
&lt;h2&gt;节点语法&lt;/h2&gt;
&lt;p&gt;Cypher 使用一对括号来表示一个节点：&lt;code&gt;()&lt;/code&gt;。这让人联想到一个圆形或一个带有圆形端盖的矩形。以下是一些节点的示例，提供了不同类型和数量的详细信息：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;()
(matrix)
(:Movie)
(matrix:Movie)
(matrix:Movie {title: &amp;#x27;The Matrix&amp;#x27;})
(matrix:Movie {title: &amp;#x27;The Matrix&amp;#x27;, released: 1997})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最简单的形式 &lt;code&gt;()&lt;/code&gt; 表示一个匿名的、未表征的节点。如果我们要稍后引用该节点，我们可以添加一个变量，例如：&lt;code&gt;(matrix)&lt;/code&gt;。变量仅限于单个语句。它在另一个语句中可能具有不同的含义或没有意义。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;:Movie&lt;/code&gt; 模式声明节点的标签。这允许我们限制模式，防止它匹配（例如）此位置具有 &lt;code&gt;Actor&lt;/code&gt; 节点的结构。&lt;/p&gt;
&lt;p&gt;节点的属性（例如 &lt;code&gt;title&lt;/code&gt;）表示为键值对的列表，括在一对大括号内，例如：&lt;code&gt;{name: &apos;Keanu Reeves&apos;}&lt;/code&gt;。属性可用于存储信息和/或限制模式。&lt;/p&gt;
&lt;h2&gt;关系语法&lt;/h2&gt;
&lt;p&gt;Cypher 使用一对破折号 (&lt;code&gt;--&lt;/code&gt;) 来表示无向关系。有向关系在一端有一个箭头 (&lt;code&gt;&amp;lt;--&lt;/code&gt;，&lt;code&gt;--&amp;gt;&lt;/code&gt;)。带括号的表达式 (&lt;code&gt;[...]&lt;/code&gt;) 可用于添加详细信息。这可能包括变量、属性和类型信息：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;--&amp;gt;
-[role]-&amp;gt;
-[:ACTED_IN]-&amp;gt;
-[role:ACTED_IN]-&amp;gt;
-[role:ACTED_IN {roles: [&amp;#x27;Neo&amp;#x27;]}]-&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在关系的括号对中找到的语法和语义与节点括号之间使用的语法和语义非常相似。可以定义一个变量（例如，&lt;code&gt;role&lt;/code&gt;），以便在语句中的其他地方使用。关系类型（例如，&lt;code&gt;:ACTED_IN&lt;/code&gt;）类似于节点的标签。属性（例如，&lt;code&gt;roles&lt;/code&gt;）与节点属性完全等效。&lt;/p&gt;
&lt;h2&gt;模式语法&lt;/h2&gt;
&lt;p&gt;结合节点和关系的语法，我们可以表达模式。以下可能是此域中的一个简单模式（或事实）：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(keanu:Person:Actor {name: &amp;#x27;Keanu Reeves&amp;#x27;})-[role:ACTED_IN {roles: [&amp;#x27;Neo&amp;#x27;]}]-&amp;gt;(matrix:Movie {title: &amp;#x27;The Matrix&amp;#x27;})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;与节点标签等效，&lt;code&gt;:ACTED_IN&lt;/code&gt; 模式声明关系的类型。变量（例如，&lt;code&gt;role&lt;/code&gt;）可以在语句中的其他地方使用以引用该关系。&lt;/p&gt;
&lt;p&gt;与节点属性一样，关系属性表示为括在一对大括号内的键/值对的列表，例如：&lt;code&gt;{roles: [&apos;Neo&apos;]}&lt;/code&gt;。在这种情况下，我们对角色使用了数组属性，允许指定多个角色。属性可用于存储信息和/或限制模式。&lt;/p&gt;
&lt;h2&gt;模式变量&lt;/h2&gt;
&lt;p&gt;为了提高模块化并减少重复，Cypher 允许将模式分配给变量。这允许检查匹配的路径，在其他表达式中使用等。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;acted_in = (:Person)-[:ACTED_IN]-&amp;gt;(:Movie)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;acted_in&lt;/code&gt; 变量将包含每个找到或创建的路径的两个节点和连接关系。有许多函数可以访问路径的详细信息，例如：&lt;code&gt;nodes(path)&lt;/code&gt;、&lt;code&gt;relationships(path)&lt;/code&gt; 和 &lt;code&gt;length(path)&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;子句&lt;/h2&gt;
&lt;p&gt;Cypher 语句通常具有多个子句，每个子句执行一个特定任务，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在图中创建和匹配模式&lt;/li&gt;
&lt;li&gt;过滤、投影、排序或分页结果&lt;/li&gt;
&lt;li&gt;组成部分语句&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过组合 Cypher 子句，您可以组成复杂的语句，表达您想要知道或创建的内容。&lt;/p&gt;
&lt;p&gt;有关 Cypher 子句及其使用的详细信息，请参阅 [Cypher 手册 → 子句](链接到 Cypher 手册 → 子句)。&lt;/p&gt;
&lt;p&gt;您还可以访问 [Cypher 速查表](链接到 Cypher 速查表) 以快速参考 Cypher 语法。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Wed, 09 Apr 2025 01:36:15 GMT</pubDate></item><item><title>Neo4j官方教程：第7节， Cypher 与 SQL 比较</title><link>http://neo4j.com.cn/topic/67f5ccf0455186f56d9f4132</link><guid>http://neo4j.com.cn/topic/67f5ccf0455186f56d9f4132</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher-intro/cypher-sql/&quot;&gt;https://neo4j.com/docs/getting-started/cypher-intro/cypher-sql/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Cypher 与 SQL 比较&lt;/h1&gt;
&lt;h2&gt;关系型 vs 图&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational-vs-graph.svg&quot; alt=&quot;image&quot;&gt;
![图 1. Northwind 数据集的关系型和图模型](插入图 1 的链接)&lt;/p&gt;
&lt;p&gt;以下查询示例使用 Northwind 数据集。它们旨在帮助熟悉 SQL 的人理解 Cypher® 并编写等效于 SQL 的 Cypher 查询。有关数据集中关系型和图模型之间差异的可视化表示，请参见图 1。&lt;/p&gt;
&lt;p&gt;请参阅&lt;a href&gt;示例数据集&lt;/a&gt;以了解如何将 Northwind 加载到您的 Neo4j 实例并尝试这些示例。&lt;/p&gt;
&lt;p&gt;有关图数据库和关系型数据库之间差异和相似之处的更深入解释，请参见&lt;a href&gt;从关系型数据库过渡到图数据库&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;查询示例&lt;/h2&gt;
&lt;h3&gt;选择和返回记录&lt;/h3&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;要选择和返回 SQL 中的记录，请从 products 表中选择所有内容：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.*
FROM products as p;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;在 Cypher 中，您 &lt;code&gt;MATCH&lt;/code&gt; 一个简单的模式：所有带有标签 &lt;code&gt;:Product&lt;/code&gt; 的节点，并 &lt;code&gt;RETURN&lt;/code&gt; 它们：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
RETURN p;
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;字段访问、排序和分页&lt;/h3&gt;
&lt;p&gt;您可以过滤掉您感兴趣的属性，而不是返回所有属性，例如 &lt;code&gt;ProductName&lt;/code&gt; 和 &lt;code&gt;UnitPrice&lt;/code&gt;。&lt;/p&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;在 SQL 中，这是您按价格对项目进行排序并返回 10 个最昂贵的项目的方式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName, p.UnitPrice
FROM products as p
ORDER BY p.UnitPrice DESC
LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;该语句在 Cypher 中类似，除了模式匹配部分：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
RETURN p.productName, p.unitPrice
ORDER BY p.unitPrice DESC
LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请记住，标签、关系类型和属性名称在 Neo4j 中区分大小写。有关命名规则的更多详细信息，请参见 [Cypher 手册 → 命名规则和建议](链接到 Cypher 手册 → 命名规则和建议)。&lt;/p&gt;
&lt;h3&gt;按名称查找单个产品&lt;/h3&gt;
&lt;p&gt;有不同的方法来查询数据库并检索单个项目，例如，名为 Chocolade 的产品。&lt;/p&gt;
&lt;h4&gt;按相等性过滤&lt;/h4&gt;
&lt;h5&gt;SQL&lt;/h5&gt;
&lt;p&gt;在 SQL 中，您可以使用 &lt;code&gt;WHERE&lt;/code&gt; 子句过滤数据：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName = &amp;#x27;Chocolade&amp;#x27;;
&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;Cypher&lt;/h5&gt;
&lt;p&gt;在 Cypher 中，&lt;code&gt;WHERE&lt;/code&gt; 子句属于 &lt;code&gt;MATCH&lt;/code&gt; 语句：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.productName = &amp;#x27;Chocolade&amp;#x27;
RETURN p.productName, p.unitPrice;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;一个较短的选项是使用标签 &lt;code&gt;productName&lt;/code&gt; 在 &lt;code&gt;MATCH&lt;/code&gt; 语句中指定产品：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product {productName:&amp;#x27;Chocolade&amp;#x27;})
RETURN p.productName, p.unitPrice;
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;索引&lt;/h3&gt;
&lt;p&gt;SQL 和 Cypher 中都提供索引，并且可以更有效地搜索特定的节点标签和属性组合。&lt;/p&gt;
&lt;p&gt;Cypher 中的索引仅用于查找查询的起点；所有后续模式匹配都通过图结构完成。Cypher 支持范围、文本、点、查找、全文和向量索引。&lt;/p&gt;
&lt;p&gt;在 Northwind 数据集中，在节点标签 &lt;code&gt;productName&lt;/code&gt; 和 &lt;code&gt;unitPrice&lt;/code&gt; 上添加索引可以更快地搜索产品及其价格：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE INDEX Product_productName IF NOT EXISTS FOR (p:Product) ON p.productName;
CREATE INDEX Product_unitPrice IF NOT EXISTS FOR (p:Product) ON p.unitPrice;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cypher 中的索引仅用于查找查询的起点。所有后续模式匹配都通过图结构完成。Cypher 支持范围、文本、点、查找、全文和向量索引。阅读有关如何在 [Cypher 手册 → 使用索引](链接到 Cypher 手册 → 使用索引) 中使用索引的更多信息。&lt;/p&gt;
&lt;h3&gt;过滤产品&lt;/h3&gt;
&lt;p&gt;有几种方法可以在 Cypher 中过滤结果，这些方法与 SQL 类似。&lt;/p&gt;
&lt;h4&gt;按列表/范围过滤&lt;/h4&gt;
&lt;h5&gt;SQL&lt;/h5&gt;
&lt;p&gt;在 SQL 中，您可以使用运算符 &lt;code&gt;IN&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName, p.UnitPrice
FROM products as p
WHERE p.ProductName IN (&amp;#x27;Chocolade&amp;#x27;,&amp;#x27;Chai&amp;#x27;);
&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;Cypher&lt;/h5&gt;
&lt;p&gt;Cypher 具有完整的集合支持，包括 &lt;code&gt;IN&lt;/code&gt; 和其他集合函数、谓词和转换：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.productName IN [&amp;#x27;Chocolade&amp;#x27;,&amp;#x27;Chai&amp;#x27;]
RETURN p.productName, p.unitPrice;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;按多个数字和文本谓词过滤&lt;/h4&gt;
&lt;h5&gt;SQL&lt;/h5&gt;
&lt;p&gt;此查询检索名称以 “C” 开头且价格大于 100 的产品：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName LIKE &amp;#x27;C%&amp;#x27; AND p.UnitPrice &amp;gt; 100;
&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;Cypher&lt;/h5&gt;
&lt;p&gt;在 Cypher 中，&lt;code&gt;LIKE&lt;/code&gt; 运算符被 &lt;code&gt;STARTS WITH&lt;/code&gt;、&lt;code&gt;CONTAINS&lt;/code&gt; 和 &lt;code&gt;ENDS WITH&lt;/code&gt; 运算符替换：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.productName STARTS WITH &amp;#x27;C&amp;#x27; AND p.unitPrice &amp;gt; 100
RETURN p.productName, p.unitPrice;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您也可以使用正则表达式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)
WHERE p.productName =~ &amp;#x27;^C.*&amp;#x27;
RETURN p.productName, p.unitPrice
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;将产品与客户连接&lt;/h3&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;在 SQL 中，如果您想查看谁购买了 Chocolade，您可以将四个表连接在一起：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT DISTINCT c.CompanyName
FROM customers AS c
JOIN orders AS o ON (c.CustomerID = o.CustomerID)
JOIN order_details AS od ON (o.OrderID = od.OrderID)
JOIN products AS p ON (od.ProductID = p.ProductID)
WHERE p.ProductName = &amp;#x27;Chocolade&amp;#x27;;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;在 Cypher 中，无需 &lt;code&gt;JOIN&lt;/code&gt; 表。您可以将连接表示为图模式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product {productName:&amp;#x27;Chocolade&amp;#x27;})&amp;lt;-[:ORDERS]-(:Order)&amp;lt;-[:PURCHASED]-(c:Customer)
RETURN DISTINCT c.companyName;
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;返回没有现有订单的客户&lt;/h3&gt;
&lt;p&gt;如果您想查看谁购买了什么以及他们总共支付了多少，则先前 SQL 查询中的 &lt;code&gt;JOIN&lt;/code&gt; 保持不变，只有过滤表达式发生变化。但是，如果您有没有任何订单的客户并且仍然想返回他们，则需要进行一些调整。&lt;/p&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;在 SQL 中，您必须使用 &lt;code&gt;OUTER JOINS&lt;/code&gt; 来确保即使其他表中没有匹配的行也返回结果：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName, sum(od.UnitPrice * od.Quantity) AS Volume
FROM customers AS c
LEFT OUTER JOIN orders AS o ON (c.CustomerID = o.CustomerID)
LEFT OUTER JOIN order_details AS od ON (o.OrderID = od.OrderID)
LEFT OUTER JOIN products AS p ON (od.ProductID = p.ProductID)
WHERE c.CompanyName = &amp;#x27;Drachenblut Delikatessen&amp;#x27;
GROUP BY p.ProductName
ORDER BY Volume DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;在 Cypher 中，客户和订单之间的 &lt;code&gt;MATCH&lt;/code&gt; 变为 &lt;code&gt;OPTIONAL MATCH&lt;/code&gt;，这等效于 &lt;code&gt;OUTER JOIN&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (c:Customer {companyName:&amp;#x27;Drachenblut Delikatessen&amp;#x27;})
OPTIONAL MATCH (p:Product)&amp;lt;-[o:ORDERS]-(:Order)&amp;lt;-[:PURCHASED]-(c)
RETURN p.productName, toInteger(sum(o.unitPrice * o.quantity)) AS volume
ORDER BY volume DESC;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;不存在的节点和关系将具有空值，这将导致属性为空，并且不会被 &lt;code&gt;sum&lt;/code&gt; 聚合。&lt;/p&gt;
&lt;h3&gt;畅销员工&lt;/h3&gt;
&lt;p&gt;前面的示例提到了聚合。通过对产品价格和订购数量求和，提供了每个客户的每个产品的聚合视图。&lt;/p&gt;
&lt;p&gt;您可以在 SQL 和 Cypher 中使用聚合函数，如 &lt;code&gt;sum&lt;/code&gt;、&lt;code&gt;count&lt;/code&gt;、&lt;code&gt;avg&lt;/code&gt; 和 &lt;code&gt;max&lt;/code&gt;。&lt;/p&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;在 SQL 中，聚合是显式的，因此您必须在 &lt;code&gt;GROUP BY&lt;/code&gt; 子句中再次提供所有分组键。要查看畅销员工，请运行以下查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT e.EmployeeID, e.FirstName, e.LastName, COUNT(*) AS Count
FROM Employee AS e
JOIN Orders AS o ON (o.EmployeeID = e.EmployeeID)
GROUP BY e.EmployeeID, e.FirstName, e.LastName
ORDER BY Count DESC
LIMIT 10;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;在 Cypher 中，聚合的分组是隐式的。只要您使用第一个聚合函数，所有非聚合列都会自动成为分组键：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (:Order)&amp;lt;-[:SOLD]-(e:Employee)
WITH e, count(*) as cnt
ORDER BY cnt DESC LIMIT 10
RETURN e.employeeID, e.firstName, e.lastName, cnt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其他聚合函数（如 &lt;code&gt;collect&lt;/code&gt;、&lt;code&gt;percentileCont&lt;/code&gt;、&lt;code&gt;stdDev&lt;/code&gt;）也可用。&lt;/p&gt;
&lt;h3&gt;员工区域&lt;/h3&gt;
&lt;p&gt;在 SQL 中，处理主详细信息可能具有挑战性。一个示例是当您有一个主要实体（主实体、头实体、父实体）和许多依赖实体（详细信息、位置、子实体）时。&lt;/p&gt;
&lt;p&gt;您可以编写一个连接两者并多次返回主数据的查询（每个详细信息一次），或者仅获取主键，然后通过该外键拉取所有详细信息行。&lt;/p&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;在 SQL 中，如果您查看每个区域的员工，则会为每个员工返回区域信息：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT e.LastName, et.Description
FROM Employee AS e
JOIN EmployeeTerritory AS et ON (et.EmployeeID = e.EmployeeID)
JOIN Territory AS t ON (et.TerritoryID = t.TerritoryID);
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;在 Cypher 中，您可以像在 SQL 中一样返回结构，也可以使用 &lt;code&gt;collect()&lt;/code&gt; 聚合函数，该函数将值聚合到集合（列表、数组）中。这样，每个父级仅返回一行，其中包含子值的内联集合：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (t:Territory)&amp;lt;-[:IN_TERRITORY]-(e:Employee)
RETURN t.territoryDescription, collect(e.lastName);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这也适用于嵌套值。&lt;/p&gt;
&lt;h3&gt;产品类别&lt;/h3&gt;
&lt;p&gt;如果您必须在 SQL 中表达类别、区域或组织层次结构，通常使用从子级到父级的外键通过自连接进行建模。在产品类别的示例中，您必须预先决定要查询多少级别的类别。&lt;/p&gt;
&lt;h4&gt;SQL&lt;/h4&gt;
&lt;p&gt;此处仅显示三个潜在级别（这意味着 &lt;code&gt;ProductCategory&lt;/code&gt; 表的 1+2+3 = 6 个自连接）：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT p.ProductName
FROM Product AS p
JOIN ProductCategory pc ON (p.CategoryID = pc.CategoryID AND pc.CategoryName = &amp;quot;Dairy Products&amp;quot;)

JOIN ProductCategory pc1 ON (p.CategoryID = pc1.CategoryID)
JOIN ProductCategory pc2 ON (pc2.ParentID = pc2.CategoryID AND pc2.CategoryName = &amp;quot;Dairy Products&amp;quot;)

JOIN ProductCategory pc3 ON (p.CategoryID = pc3.CategoryID)
JOIN ProductCategory pc4 ON (pc3.ParentID = pc4.CategoryID)
JOIN ProductCategory pc5 ON (pc4.ParentID = pc5.CategoryID AND pc5.CategoryName = &amp;quot;Dairy Products&amp;quot;)
;
&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Cypher&lt;/h4&gt;
&lt;p&gt;Cypher 能够仅使用适当的关系来表达任何深度的层次结构。可变级别由可变长度路径表示，这些路径由关系类型后的星号 &lt;code&gt;*&lt;/code&gt; 和可选限制 (&lt;code&gt;min..max&lt;/code&gt;) 表示：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Product)-[:PART_OF]-&amp;gt;(l:Category)-[:PARENT*0..]-&amp;gt;(:Category {name:&amp;#x27;Dairy Products&amp;#x27;})
RETURN p.name;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Wed, 09 Apr 2025 01:27:12 GMT</pubDate></item><item><title>Neo4j官方教程：第6节， 什么是 Cypher</title><link>http://neo4j.com.cn/topic/67f5cb22455186f56d9f4131</link><guid>http://neo4j.com.cn/topic/67f5cb22455186f56d9f4131</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/cypher/&quot;&gt;https://neo4j.com/docs/getting-started/cypher/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;什么是 Cypher&lt;/h1&gt;
&lt;p&gt;本页介绍 Cypher® 的基础知识。有关完整文档，请参阅 Cypher。&lt;/p&gt;
&lt;h2&gt;Cypher 学习&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-learning-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 1. Cypher 查询的可视化表示](插入图 1 的链接)&lt;/p&gt;
&lt;p&gt;Cypher 是 Neo4j 的声明式和 GQL 兼容的查询语言。Cypher 通过 openCypher 项目以开源形式提供，类似于 SQL，但针对图进行了优化。&lt;/p&gt;
&lt;p&gt;Cypher 直观且接近自然语言，通过基于 ASCII 艺术类型语法的自身设计，提供了一种可视化匹配模式和关系的方式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;(:nodes)-[:ARE_CONNECTED_TO]-&amp;gt;(:otherNodes)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;圆括号用于表示 &lt;code&gt;(:Nodes)&lt;/code&gt;，而 &lt;code&gt;-[:ARROWS]-&amp;gt;&lt;/code&gt; 用于表示 &lt;code&gt;(:Nodes)&lt;/code&gt; 之间的关系。使用此查询语法，您可以对图执行创建、读取、更新或删除 (CRUD) 操作。&lt;/p&gt;
&lt;p&gt;要快速浏览而无需安装，请获取免费的 Aura 实例。使用右上角的毕业帽图标访问交互式指南。“查询基础”为您提供了 Cypher 的实践介绍。&lt;/p&gt;
&lt;h2&gt;Cypher 如何工作？&lt;/h2&gt;
&lt;p&gt;Neo4j 的图模型由节点和关系组成，它们也可以具有分配的属性。使用节点和关系，您可以构建强大的模式，这些模式可以表达简单或复杂的模式。&lt;/p&gt;
&lt;p&gt;模式识别是关键的基本认知过程，这使得利用模式匹配的 Cypher 直观且易于学习。&lt;/p&gt;
&lt;h2&gt;Cypher 语法&lt;/h2&gt;
&lt;p&gt;Cypher 的构造基于英语散文和图像。这使得查询易于编写和阅读。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypherintro-graph.svg&quot; alt=&quot;image&quot;&gt;
![图 2. 包含四个节点和三个关系的图示例](插入图 2 的链接)&lt;/p&gt;
&lt;p&gt;如果要用英语表示此图中的数据，它可能读起来像这样：“Sally 喜欢图。Sally 和 John 是朋友。Sally 为 Neo4j 工作。”&lt;/p&gt;
&lt;p&gt;现在，如果要用 Cypher 编写相同的信息，它将如下所示：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(:Sally)-[:LIKES]-&amp;gt;(:Graphs)
(:Sally)-[:IS_FRIENDS_WITH]-&amp;gt;(:John)
(:Sally)-[:WORKS_FOR]-&amp;gt;(:Neo4j)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;但是，为了使此信息在图中，首先需要将其表示为节点和关系。&lt;/p&gt;
&lt;h2&gt;节点&lt;/h2&gt;
&lt;p&gt;在属性图模型中，主要组件是节点和关系。节点通常用于表示数据模型中的名词或对象。在前面的示例中，Sally、John、Graphs 和 Neo4j 是节点：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypherintro-nodes.svg&quot; alt=&quot;image&quot;&gt;
![图 3. 节点的可视化表示](插入图 3 的链接)&lt;/p&gt;
&lt;p&gt;在 Cypher 中，您可以通过用括号将其括起来来描述一个节点，例如 &lt;code&gt;(node)&lt;/code&gt;。括号是构成可视化中节点的圆圈的表示。&lt;/p&gt;
&lt;h2&gt;节点标签&lt;/h2&gt;
&lt;p&gt;节点可以通过标签分组在一起。它们像标签一样工作，允许您指定要查找或创建的某些类型的实体。标签还有助于 Cypher 区分实体并优化查询的执行。&lt;/p&gt;
&lt;p&gt;在示例中，Sally 和 John 都可以归类在 &lt;code&gt;Person&lt;/code&gt; 标签下，&lt;code&gt;Graphs&lt;/code&gt; 可以接收 &lt;code&gt;Technology&lt;/code&gt; 标签，而 &lt;code&gt;Neo4j&lt;/code&gt; 可以标记为 &lt;code&gt;Company&lt;/code&gt;：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypher-graph-nodes-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 4. 分组在标签中的节点。请注意，Sally、John、Graphs 和 Neo4j 现在是属性](插入图 4 的链接)&lt;/p&gt;
&lt;p&gt;在关系数据库上下文中，这与告诉 SQL 在哪个表中查找特定行相同。就像您可以告诉 SQL 从 &lt;code&gt;Person&lt;/code&gt; 表中查询人员的信息一样，您也可以告诉 Cypher 仅检查 &lt;code&gt;Person&lt;/code&gt; 标签以获取该信息。&lt;/p&gt;
&lt;p&gt;如果您不指定标签让 Cypher 过滤掉不匹配的节点类别，则查询将检查数据库中的所有节点。这可能会影响非常大的图中的性能。&lt;/p&gt;
&lt;h2&gt;节点变量&lt;/h2&gt;
&lt;p&gt;虽然不是强制性的，但在查询数据库时，变量特别有用，因为它们允许在后续子句中引用指定的节点，而无需完整地编写其标签。&lt;/p&gt;
&lt;p&gt;变量可以是单个字母或单词，并且应以小写形式书写。例如，如果要将所有标记为 &lt;code&gt;Person&lt;/code&gt; 的节点绑定到变量 &lt;code&gt;p&lt;/code&gt;，则可以编写 &lt;code&gt;(p:Person)&lt;/code&gt;。同样，如果要使用完整的单词，则可以编写 &lt;code&gt;(person:Person)&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;MATCH&lt;/code&gt; 查询中检索所有标记为 &lt;code&gt;Person&lt;/code&gt; 的节点，如下所示：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;没有变量&lt;/th&gt;
&lt;th&gt;有变量&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MATCH (:Person)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MATCH (p:Person)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RETURN Person&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RETURN p&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;请注意，在没有变量的示例中，节点 &lt;code&gt;Person&lt;/code&gt; 前面有一个冒号 &lt;code&gt;(:)&lt;/code&gt;。这是防止类型或标签成为变量的方式。&lt;/p&gt;
&lt;p&gt;如果您忘记添加冒号并像这样编写查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (Person)
RETURN Person
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;那么 &lt;code&gt;Person&lt;/code&gt; 将是一个变量，而不是类型或标签。&lt;/p&gt;
&lt;h2&gt;关系&lt;/h2&gt;
&lt;p&gt;图数据库的优点之一是您可以存储有关元素（节点）如何以关系的形式相互关联的信息。&lt;/p&gt;
&lt;p&gt;在 Cypher 中，关系表示为方括号和连接两个节点的箭头（例如 &lt;code&gt;(Node1)-[]-&amp;gt;(Node2)&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;在示例中，包含 &lt;code&gt;:LIKES&lt;/code&gt;、&lt;code&gt;:IS_FRIENDS_WITH&lt;/code&gt; 和 &lt;code&gt;:WORKS_FOR&lt;/code&gt; 的行表示节点之间的关系：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypherintro-graph.svg&quot; alt=&quot;image&quot;&gt;
![图 5. 具有节点和关系的图](插入图 5 的链接)&lt;/p&gt;
&lt;p&gt;请记住始终在关系类型前面加上冒号。如果您忘记了，并编写了诸如 &lt;code&gt;(:Person)-[LIKES]-&amp;gt;(:Technology)&lt;/code&gt; 之类的查询，则 &lt;code&gt;[LIKES]&lt;/code&gt; 将表示关系变量，而不是关系类型。&lt;/p&gt;
&lt;h2&gt;关系方向&lt;/h2&gt;
&lt;p&gt;关系始终具有由箭头指示的方向。&lt;/p&gt;
&lt;p&gt;它们可以从左到右：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(p:Person)-[:LIKES]-&amp;gt;(t:Technology)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从右到左：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(p:Person)&amp;lt;-[:LIKES]-(t:Technology)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或者是不定向的（未指定方向）：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:LIKES]-(t:Technology)
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;无向关系&lt;/h3&gt;
&lt;p&gt;无向关系并不意味着它没有方向，而是可以在任一方向上遍历它。虽然您无法创建没有方向的关系，但您可以查询它们的不定向关系（在示例中，使用 &lt;code&gt;MATCH&lt;/code&gt; 子句）。&lt;/p&gt;
&lt;p&gt;在查询中使用无向关系在您不知道方向时特别有用，因为如果您编写了方向错误的查询，Cypher 将不会返回任何内容。因此，Cypher 将检索由指定关系类型连接的所有节点，而不管方向如何。&lt;/p&gt;
&lt;p&gt;因为查询中的无向关系被遍历两次（每个方向一次），所以相同的模式将被返回两次。这可能会影响查询的性能。&lt;/p&gt;
&lt;h2&gt;关系类型&lt;/h2&gt;
&lt;p&gt;关系类型对关系进行分类并为其添加含义，类似于标签如何将节点分组在一起。通常认为最好使用动词或派生词作为关系类型。该类型描述了节点如何相互关联。这样，Cypher 几乎就像自然语言一样，其中节点是主语和宾语（名词），而关系（动词）是关联它们的动作词。&lt;/p&gt;
&lt;p&gt;在前面的示例中，关系类型为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[:LIKES]&lt;/code&gt; - 传达 Sally（一个节点）喜欢图（另一个节点）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[:IS_FRIENDS_WITH]&lt;/code&gt; - 传达 Sally 和 John 是朋友。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[:WORKS_FOR]&lt;/code&gt; - 传达 Sally 为 Neo4j 工作。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;关系变量&lt;/h2&gt;
&lt;p&gt;变量可以像用于节点一样用于关系。指定变量后，您可以在查询的后面使用它来引用该关系。&lt;/p&gt;
&lt;p&gt;看这个例子：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[r:LIKES]-&amp;gt;(t:Technology)
RETURN p,r,t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此查询为节点标签（&lt;code&gt;p&lt;/code&gt; 代表 &lt;code&gt;Person&lt;/code&gt;，&lt;code&gt;t&lt;/code&gt; 代表 &lt;code&gt;Technology&lt;/code&gt;）和关系类型（&lt;code&gt;r&lt;/code&gt; 代表 &lt;code&gt;:LIKES&lt;/code&gt;）指定变量。在 &lt;code&gt;RETURN&lt;/code&gt; 子句中，您可以使用变量（即 &lt;code&gt;p&lt;/code&gt;、&lt;code&gt;r&lt;/code&gt; 和 &lt;code&gt;t&lt;/code&gt;）来返回绑定的实体。&lt;/p&gt;
&lt;p&gt;这将是您的结果：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypherintro-variables.svg&quot; alt=&quot;image&quot;&gt;
![图 6. 使用节点和关系变量的示例查询的结果](插入图 6 的链接)&lt;/p&gt;
&lt;p&gt;表 1. 结果&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;p&lt;/th&gt;
&lt;th&gt;r&lt;/th&gt;
&lt;th&gt;t&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;(:Person)&lt;/td&gt;
&lt;td&gt;[:LIKES]&lt;/td&gt;
&lt;td&gt;(:Technology)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;行数：1&lt;/p&gt;
&lt;p&gt;请记住始终在关系类型前面加上冒号。如果您忘记了，并像这样编写查询：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(Person)-[LIKES]-&amp;gt;(Technology)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;[LIKES]&lt;/code&gt; 将表示关系变量，而不是关系类型。在这种情况下，由于未声明关系类型，Cypher 将搜索所有类型的关系，以便检索查询的结果。&lt;/p&gt;
&lt;h2&gt;属性&lt;/h2&gt;
&lt;p&gt;属性值可以添加到节点和关系，并且可以是各种数据类型。有关值和类型的完整列表，请参阅 Cypher 手册 → 值和类型。&lt;/p&gt;
&lt;p&gt;组织前面示例中数据的另一种方法是添加一个属性 &lt;code&gt;name&lt;/code&gt;，并将 &lt;code&gt;Sally&lt;/code&gt; 和 &lt;code&gt;John&lt;/code&gt; 作为 &lt;code&gt;Person&lt;/code&gt; 标记节点上的属性值：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/cypherintro-properties.svg&quot; alt=&quot;image&quot;&gt;
![图 7. 具有节点和关系属性的图示例](插入图 7 的链接)&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (p:Person {name:&amp;#x27;Sally&amp;#x27;})-[r:IS_FRIENDS_WITH]-&amp;gt;(p:Person {name:&amp;#x27;John&amp;#x27;})
RETURN p, r
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;属性用花括号 (&lt;code&gt;{}&lt;/code&gt;) 括起来，键后跟一个冒号，值用单引号或双引号括起来。&lt;/p&gt;
&lt;p&gt;如果您已经将 Sally 和 John 添加为节点标签，但想将它们更改为节点属性，则需要重构您的图。重构是数据建模中的一种策略，您可以在本教程中了解更多信息。&lt;/p&gt;
&lt;h2&gt;Cypher 中的模式&lt;/h2&gt;
&lt;p&gt;图模式匹配位于 Cypher 的核心。它是通过应用声明式模式来导航、描述和从图中提取数据的机制。&lt;/p&gt;
&lt;p&gt;考虑这个例子：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;(p:Person {name: &amp;quot;Sally&amp;quot;})-[r:LIKES]-&amp;gt;(g:Technology {type: &amp;quot;Graphs&amp;quot;})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这段 Cypher 代表一个模式，但它不是一个查询。它仅表示名称属性为 Sally 的 &lt;code&gt;Person&lt;/code&gt; 节点与类型属性为 Graphs 的 &lt;code&gt;Technology&lt;/code&gt; 节点具有 &lt;code&gt;LIKES&lt;/code&gt; 关系。&lt;/p&gt;
&lt;p&gt;为了对此模式执行某些操作，例如将其添加到图或从中检索，您需要查询数据库。&lt;/p&gt;
&lt;p&gt;例如，您可以使用 &lt;code&gt;CREATE&lt;/code&gt; 子句将此信息添加到数据库：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (p:Person {name: &amp;quot;Sally&amp;quot;})-[r:LIKES]-&amp;gt;(t:Technology {type: &amp;quot;Graphs&amp;quot;})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;一旦此数据写入数据库，您可以使用以下模式检索它：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person {name: &amp;quot;Sally&amp;quot;})-[r:LIKES]-&amp;gt;(t:Technology {type: &amp;quot;Graphs&amp;quot;})
RETURN p,r,t
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;模式变量&lt;/h2&gt;
&lt;p&gt;与节点和关系一样，您也可以将变量用于模式。有关更多信息，请参阅 Cypher 手册 → 模式 → 语法和语义。&lt;/p&gt;
&lt;h2&gt;继续学习&lt;/h2&gt;
&lt;p&gt;现在已经介绍了基本的 Cypher 概念，您可以参加有关如何开始使用 Cypher 的教程，以学习如何编写自己的查询。在 Cypher 手册中，您可以找到更多信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如何编写基本查询以及可以使用哪些子句从数据库读取数据。&lt;/li&gt;
&lt;li&gt;模式如何工作以及如何使用它们来导航、描述和从图中提取数据。&lt;/li&gt;
&lt;li&gt;Cypher 中有哪些值和类型以及函数可用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;从 SQL 到 Cypher&lt;/h2&gt;
&lt;p&gt;如果您具有 SQL 背景并且是图数据库的新手，则以下是一些资源，可用于获取有关关键差异以及过渡到图的更多信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cypher 和 SQL 之间的主要区别&lt;/li&gt;
&lt;li&gt;从关系型数据库过渡到图数据库&lt;/li&gt;
&lt;li&gt;参考：将 Cypher 与 SQL 进行比较&lt;/li&gt;
&lt;li&gt;操作方法：从 RDBMS 导入到图&lt;/li&gt;
&lt;li&gt;教程：将数据从关系数据库导入到 Neo4j&lt;/li&gt;
&lt;li&gt;操作方法：将数据从关系型建模到图&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;从 NoSQL 到图&lt;/h2&gt;
&lt;p&gt;如果您熟悉 NoSQL（“不仅仅是 SQL”）系统，您还可以了解更多关于如何过渡到图数据库的信息。&lt;/p&gt;
&lt;h2&gt;GraphAcademy&lt;/h2&gt;
&lt;p&gt;通过 Cypher 基础课程，您可以在 60 分钟内学习 Cypher，并使用沙盒进行练习。&lt;/p&gt;
&lt;h2&gt;其他资源&lt;/h2&gt;
&lt;p&gt;有关如何扩展您对 Cypher 的知识的更多建议，请参阅资源。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Wed, 09 Apr 2025 01:19:30 GMT</pubDate></item><item><title>Neo4j官方教程：第5节，从NoSQL到图数据库的转型</title><link>http://neo4j.com.cn/topic/67f4e38d455186f56d9f4130</link><guid>http://neo4j.com.cn/topic/67f4e38d455186f56d9f4130</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/graphdb-vs-nosql/&quot;&gt;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/graphdb-vs-nosql/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;从NoSQL到图数据库的转型&lt;/h3&gt;
&lt;p&gt;虽然命名不够直观，但NoSQL（“不仅是SQL”）领域汇集了许多有趣的解决方案，它们提供多样化的数据模型和数据库系统。相比传统SQL解决方案，这些技术针对特定使用场景和数据结构往往更具优势。&lt;/p&gt;
&lt;p&gt;随着NoSQL运动的兴起，大型关系型系统&amp;quot;一刀切&amp;quot;的解决方案模式已被取代，取而代之的是根据具体需求寻找合适工具的理性决策。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 08:51:25 GMT</pubDate></item><item><title>《Neo4j 官方教程中文版》Neo4j首选学习资料（持续更新中）</title><link>http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f</link><guid>http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;h3&gt;Neo4j 官方教程（持续更新中）&lt;/h3&gt;
&lt;p&gt;本教程引用Neo4j官方文档： &lt;a href=&quot;https://neo4j.com/docs/&quot;&gt;https://neo4j.com/docs/&lt;/a&gt;，内容持续更新中&lt;/p&gt;
&lt;h3&gt;目录&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4c1f2c181bb8b583a8a67&quot;&gt;Neo4j官方教程：第1节，Neo4j是什么&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f4c2c9c181bb8b583a8a68&quot;&gt;Neo4j官方教程：第2节，什么是图数据库&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cbcf455186f56d9f412d&quot;&gt;Neo4j官方教程：第3节，图数据库概念&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf71455186f56d9f412e&quot;&gt;Neo4j官方教程：第4节，从关系型数据库过渡到图数据库&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f4e38d455186f56d9f4130&quot;&gt;Neo4j官方教程：第5节，从NoSQL到图数据库的转型&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f5cb22455186f56d9f4131&quot;&gt;Neo4j官方教程：第6节， 什么是 Cypher&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f5ccf0455186f56d9f4132&quot;&gt;Neo4j官方教程：第7节， Cypher 与 SQL 比较&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f5cf0f455186f56d9f4133&quot;&gt;Neo4j官方教程：第8节， 模式&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f5d4a0455186f56d9f4134&quot;&gt;Neo4j官方教程：第9节，实践中的模式&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f5db4e455186f56d9f4135&quot;&gt;Neo4j官方教程：第10节，获取正确的结果&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f867115885e744204e1838&quot;&gt;Neo4j官方教程：第11节，更新数据&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67f869905885e744204e1839&quot;&gt;Neo4j官方教程：第12节，编写大型语句&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67fcc245a755994623e85dc4&quot;&gt;Neo4j官方教程：第13节， Cypher 中的子查询&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67fcc2eba755994623e85dc5&quot;&gt;Neo4j官方教程：第14节，定义模式&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67fcc47aa755994623e85dc6&quot;&gt;Neo4j官方教程：第15节，日期、日期时间和持续时间&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/67fcc77da755994623e85dc7&quot;&gt;Neo4j官方教程：第16节， 如何扩展 Cypher&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/6800a7d2a755994623e85dc8&quot;&gt;Neo4j官方教程：第17节， 导入数据&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/6800a9ffa755994623e85dc9&quot;&gt;Neo4j官方教程：第18节， Cypher 资源&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/680b51dfb13f67342db8ad61&quot;&gt;Neo4j官方教程：第19节， 图数据建模是什么&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/680df39fb13f67342db8ad62&quot;&gt;Neo4j官方教程：第20节，创建图数据模型&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/6826fa35b13f67342db8ad68&quot;&gt;Neo4j官方教程：第21节，重构图数据模型&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/682700deb13f67342db8ad69&quot;&gt;Neo4j官方教程：第22节，数据建模设计&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/686b8d6da8f5aea0094a7c64&quot;&gt;Neo4j官方教程：第23节，版本控制&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/686b8eaaa8f5aea0094a7c65&quot;&gt;Neo4j官方教程：第24节，从关系型数据模型到图数据模型的建模&lt;/a&gt;
&lt;a href=&quot;http://neo4j.com.cn/topic/686b8f2ea8f5aea0094a7c66&quot;&gt;Neo4j官方教程：第25节，图数据建模技巧&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 07:26:09 GMT</pubDate></item><item><title>Neo4j官方教程：第4节，从关系型数据库过渡到图数据库</title><link>http://neo4j.com.cn/topic/67f4cf71455186f56d9f412e</link><guid>http://neo4j.com.cn/topic/67f4cf71455186f56d9f412e</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/graphdb-vs-rdbms/&quot;&gt;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/graphdb-vs-rdbms/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;从关系型数据库过渡到图数据库&lt;/h1&gt;
&lt;h2&gt;简介&lt;/h2&gt;
&lt;p&gt;本文旨在解释关系型数据库和图数据库在结构和数据模型上的概念差异。同时，概述了使用这两种数据库类型的相似和不同之处，从关系型和图查询语言到应用程序与数据库的交互。&lt;/p&gt;
&lt;h2&gt;关系型数据库概述&lt;/h2&gt;
&lt;p&gt;关系型数据库自 80 年代以来一直是软件应用的主力，至今仍然如此。它们在具有预定义列类型的表中存储高度结构化的数据，每个表包含多行特定类型的信息。由于其组织的严格性，关系型数据库要求开发人员和应用程序严格地组织应用中使用的数据。&lt;/p&gt;
&lt;p&gt;在关系型数据库中，对其他行和表的引用通过外键列引用主键属性来表示。连接操作在查询时通过匹配所有相关表中的主键和外键来计算。这些操作计算量大且内存密集，成本呈指数增长。&lt;/p&gt;
&lt;p&gt;当模型中出现多对多关系时，必须引入连接表（或关联实体表），其中包含参与表的外键，这进一步增加了连接操作的成本。下图展示了通过创建 &lt;code&gt;Person-Department&lt;/code&gt; 连接表将 &lt;code&gt;Person&lt;/code&gt;（来自 &lt;code&gt;Person&lt;/code&gt; 表）连接到 &lt;code&gt;Department&lt;/code&gt;（在 &lt;code&gt;Department&lt;/code&gt; 表中）的概念，该表在一列中包含人员 ID，在下一列中包含关联部门的 ID。&lt;/p&gt;
&lt;h3&gt;关系模型&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_model.svg&quot; alt=&quot;image&quot;&gt;
![图 1. 关系模型](插入图 1 的链接)&lt;/p&gt;
&lt;p&gt;虽然并非所有用例都适合这种严格的数据模型，但由于缺乏可行的替代方案以及对关系型数据库的广泛支持，使得替代模型难以进入主流。然而，NoSQL 时代到来，满足了用户和企业的一些需求，但仍然忽略了数据之间连接的重要性。这就是图数据库诞生的原因。它们旨在为我们今天所生活的互联世界提供最大的优势。&lt;/p&gt;
&lt;h2&gt;将关系型知识转化为图&lt;/h2&gt;
&lt;p&gt;与其他数据库管理系统不同，在图数据模型中，关系与数据本身具有同等重要性。这意味着我们不需要使用特殊属性（如外键）或带外处理（如 map-reduce）来推断实体之间的连接。&lt;/p&gt;
&lt;p&gt;通过将节点和关系组装成连接结构，图数据库使我们能够构建简单而复杂的模型，这些模型与我们的问题域紧密映射。数据保持与现实世界相似的形式——小型、规范化但富有连接的实体。这允许您从任何可想象的兴趣点查询和查看数据，支持许多不同的用例。&lt;/p&gt;
&lt;p&gt;图数据库模型中的每个节点（实体或属性）直接且物理地包含关系记录列表，这些记录表示与其他节点的关系。这些关系记录按类型和方向组织，并且可以包含其他属性。每当您运行等效于 &lt;code&gt;JOIN&lt;/code&gt; 操作时，图数据库都会使用此列表，直接访问连接的节点，从而无需进行昂贵的搜索和匹配计算。&lt;/p&gt;
&lt;p&gt;这种将关系预先物化到数据库结构中的能力使 Neo4j 能够提供比其他数据库高几个数量级的性能，尤其是在连接密集型查询中，从而使用户能够利用从分钟到毫秒的优势。
&lt;a href=&quot;https://www.youtube.com/embed/NO3C-CWykkY?start=294&amp;amp;enablejsapi=1&amp;amp;origin=https%3A%2F%2Fneo4j.com&quot;&gt;https://www.youtube.com/embed/NO3C-CWykkY?start=294&amp;amp;enablejsapi=1&amp;amp;origin=https%3A%2F%2Fneo4j.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;数据模型差异&lt;/h2&gt;
&lt;p&gt;正如您可能从上面讨论的结构差异中想象的那样，关系型与图的数据模型非常不同。直接的图结构产生比使用传统关系型或其他 NoSQL 数据库产生的更简单、更具表现力的数据模型。&lt;/p&gt;
&lt;p&gt;如果您习惯于使用关系型数据库进行建模，请记住设计良好的规范化实体关系图的简易性和美观性——一个简单、易于理解的模型，您可以快速与同事和领域专家在白板上进行讨论。图正是如此——一个清晰的领域模型，专注于您希望有效支持的用例。&lt;/p&gt;
&lt;p&gt;让我们比较两个数据模型，以展示关系型和图之间的结构差异。&lt;/p&gt;
&lt;h3&gt;关系型作为图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_as_graph.jpg&quot; alt=&quot;image&quot;&gt;
![图 2. 关系型 - Person 和 Department 表](插入图 2 的链接)&lt;/p&gt;
&lt;p&gt;在上面的关系型示例中，我们在左侧的 &lt;code&gt;Person&lt;/code&gt; 表（可能数百万行）中搜索用户 Alice 及其人员 ID 815。然后，我们搜索 &lt;code&gt;Person-Department&lt;/code&gt; 表（橙色中间表）以找到引用 Alice 的人员 ID (815) 的所有行。一旦我们检索到 3 个相关行，我们就转到右侧的 &lt;code&gt;Department&lt;/code&gt; 表以搜索部门 ID 的实际值（111、119、181）。现在我们知道 Alice 是 &lt;code&gt;4Future&lt;/code&gt;、&lt;code&gt;P0815&lt;/code&gt; 和 &lt;code&gt;A42&lt;/code&gt; 部门的成员。&lt;/p&gt;
&lt;h3&gt;关系图模型&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/relational_graph_model-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 3. 图 - Alice 和三个部门作为节点](插入图 3 的链接)&lt;/p&gt;
&lt;p&gt;在上面的图版本中，我们有一个 Alice 的单个节点，标签为 &lt;code&gt;Person&lt;/code&gt;。Alice 属于 3 个不同的部门，因此我们为每个部门创建一个节点，标签为 &lt;code&gt;Department&lt;/code&gt;。要找出 Alice 属于哪些部门，我们将搜索图中的 Alice 节点，然后遍历从 Alice 到 &lt;code&gt;Department&lt;/code&gt; 节点的所有 &lt;code&gt;BELONGS_TO&lt;/code&gt; 关系。这就是我们所需要的——一个单跳，不涉及任何查找。&lt;/p&gt;
&lt;p&gt;有关此主题的更多信息，请参见数据建模部分。&lt;/p&gt;
&lt;h2&gt;数据存储和检索&lt;/h2&gt;
&lt;p&gt;使用 SQL 查询关系型数据库很容易，SQL 是一种声明式查询语言，允许在数据库工具中进行简单的即席查询，以及从应用程序代码进行特定于用例的查询。甚至对象关系映射器 (ORM) 也在底层使用 SQL 与数据库通信。&lt;/p&gt;
&lt;p&gt;图数据库有类似的东西吗？是的！&lt;/p&gt;
&lt;p&gt;Cypher® 是 Neo4j 的声明式图查询语言，建立在 SQL 的基本概念和子句之上，但具有许多额外的图特定功能，可以轻松处理您的图模型。&lt;/p&gt;
&lt;p&gt;如果您曾经尝试编写具有大量连接的 SQL 语句，您就会知道，由于 SQL 语法中的所有技术噪音，您很快就会忘记查询的实际作用。在 Cypher 中，语法保持简洁，并专注于域组件及其之间的连接，以更直观和清晰地表达查找或创建数据的模式。基本模式匹配之外的其他子句与 SQL 非常相似，因为 Cypher 是建立在前辈语言的基础上的。&lt;/p&gt;
&lt;p&gt;我们将在即将到来的指南中介绍 Cypher 查询语言语法，但让我们看一个 SQL 查询与 Cypher 查询有何不同的简短示例。在上面数据建模示例中的组织域中，列出 IT 部门员工的 SQL 语句是什么样的，它与 Cypher 语句相比如何？&lt;/p&gt;
&lt;h3&gt;SQL 语句&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;SELECT name FROM Person
LEFT JOIN Person_Department
  ON Person.Id = Person_Department.PersonId
LEFT JOIN Department
  ON Department.Id = Person_Department.DepartmentId
WHERE Department.name = &amp;quot;IT Department&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Cypher 语句&lt;/h3&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;MATCH (p:Person)-[:WORKS_AT]-&amp;gt;(d:Dept)
WHERE d.name = &amp;quot;IT Department&amp;quot;
RETURN p.name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您可以在即将到来的 Cypher 查询语言和从 SQL 过渡到 Cypher 的章节中找到有关 Cypher 语法的更多信息。&lt;/p&gt;
&lt;h2&gt;从关系型过渡到图 - 实践&lt;/h2&gt;
&lt;p&gt;如果您决定将数据从关系型数据库迁移到图数据库，那么转换应用程序以使用 Neo4j 的步骤实际上非常简单。您可以像使用其他数据库一样，使用为您的技术栈或编程语言设计的驱动程序或连接器库连接到 Neo4j。感谢 Neo4j 及其社区，几乎所有流行的编程语言都有模仿现有数据库驱动程序习惯用法和方法的 Neo4j 驱动程序。&lt;/p&gt;
&lt;p&gt;例如，Neo4j JDBC 驱动程序将像这样用于查询数据库以获取 John 的部门：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-java&quot;&gt;&lt;code&gt;Connection con = DriverManager.getConnection(&amp;quot;jdbc:neo4j:&amp;#x2F;&amp;#x2F;localhost:7474&amp;#x2F;&amp;quot;);

String query =
    &amp;quot;MATCH (:Person {name:{1}})-[:EMPLOYEE]-(d:Department) RETURN d.name as dept&amp;quot;;
try (PreparedStatement stmt = con.prepareStatement(QUERY)) {
    stmt.setString(1,&amp;quot;John&amp;quot;);
    ResultSet rs = stmt.executeQuery();
    while(rs.next()) {
        String department = rs.getString(&amp;quot;dept&amp;quot;);
        ....
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;有关更多信息，您可以访问我们的构建应用程序页面，以了解如何使用不同的编程语言连接到 Neo4j。&lt;/p&gt;
&lt;h2&gt;资源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;免费电子书：关系型到图&lt;/li&gt;
&lt;li&gt;DZone Refcard：从关系型到图&lt;/li&gt;
&lt;li&gt;数据建模：关系型到图&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 07:25:37 GMT</pubDate></item><item><title>Neo4j官方教程：第3节，图数据库概念</title><link>http://neo4j.com.cn/topic/67f4cbcf455186f56d9f412d</link><guid>http://neo4j.com.cn/topic/67f4cbcf455186f56d9f412d</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/&quot;&gt;https://neo4j.com/docs/getting-started/appendix/graphdb-concepts/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;图数据库概念&lt;/h1&gt;
&lt;h2&gt;简介&lt;/h2&gt;
&lt;p&gt;本指南涵盖图数据库的基础知识。&lt;/p&gt;
&lt;p&gt;Neo4j 使用属性图数据库模型。图数据结构由节点（离散对象）组成，这些节点可以通过关系连接。下图是一个包含三个节点（圆圈）和三个关系（箭头）的图的示例。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graph_concept_three_nodes-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 1. 图结构的概念](插入图 1 的链接)&lt;/p&gt;
&lt;p&gt;Neo4j 属性图数据库模型包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;节点&lt;/strong&gt;：描述域的实体（离散对象）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;标签&lt;/strong&gt;：节点可以有零个或多个标签，用于定义（分类）它们是什么类型的节点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关系&lt;/strong&gt;：描述源节点和目标节点之间的连接。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方向&lt;/strong&gt;：关系始终具有方向（单向）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：关系必须具有类型（一种类型），用于定义（分类）它们是什么类型的关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;属性&lt;/strong&gt;：节点和关系可以具有属性（键值对），用于进一步描述它们。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在数学中，图论是研究图的学科。&lt;/p&gt;
&lt;p&gt;在图论中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点也称为顶点或点。&lt;/li&gt;
&lt;li&gt;关系也称为边、链接或线。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;示例图&lt;/h2&gt;
&lt;p&gt;下图介绍了属性图的基本概念：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graph_simple-arr.svg&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;![图 2. 示例图](插入图 2 的链接)&lt;/p&gt;
&lt;p&gt;要创建示例图，请使用 Cypher® 子句 &lt;code&gt;CREATE&lt;/code&gt;。&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Person:Actor {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})-[:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;]}]-&amp;gt;(:Movie {title: &amp;#x27;Forrest Gump&amp;#x27;, released: 1994})&amp;lt;-[:DIRECTED]-(:Person {name: &amp;#x27;Robert Zemeckis&amp;#x27;, born: 1951})
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;节点&lt;/h2&gt;
&lt;p&gt;节点用于表示域的实体（离散对象）。&lt;/p&gt;
&lt;p&gt;最简单的图是单个节点，没有关系。 考虑以下图，它由一个节点组成。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graph_single_node-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 3. 节点](插入图 3 的链接)&lt;/p&gt;
&lt;p&gt;节点标签是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Person&lt;/li&gt;
&lt;li&gt;Actor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;属性是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;name: Tom Hanks&lt;/li&gt;
&lt;li&gt;born: 1956&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以使用 Cypher 使用以下查询创建节点：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Person:Actor {name: &amp;#x27;Tom Hanks&amp;#x27;, born: 1956})
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;节点标签&lt;/h2&gt;
&lt;p&gt;标签通过将节点分组（分类）到集合中来塑造域，其中具有特定标签的所有节点都属于同一集合。&lt;/p&gt;
&lt;p&gt;例如，所有表示用户的节点都可以标记为标签 &lt;code&gt;User&lt;/code&gt;。 这样，您可以要求 Neo4j 仅对您的用户节点执行操作，例如查找具有给定名称的所有用户。&lt;/p&gt;
&lt;p&gt;由于标签可以在运行时添加和删除，因此它们也可以用于标记节点的临时状态。 &lt;code&gt;Suspended&lt;/code&gt; 标签可用于表示已暂停的银行帐户，而 &lt;code&gt;Seasonal&lt;/code&gt; 标签可以表示当前处于季节性的蔬菜。&lt;/p&gt;
&lt;p&gt;一个节点可以有零个或多个标签。&lt;/p&gt;
&lt;p&gt;在示例图中，节点标签 &lt;code&gt;Person&lt;/code&gt;、&lt;code&gt;Actor&lt;/code&gt; 和 &lt;code&gt;Movie&lt;/code&gt; 用于描述（分类）节点。 可以添加更多标签来表达数据的不同维度。&lt;/p&gt;
&lt;p&gt;下图显示了多个标签的使用。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-simple-labels-multi-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 4. 多个标签](插入图 4 的链接)&lt;/p&gt;
&lt;h2&gt;关系&lt;/h2&gt;
&lt;p&gt;关系描述了源节点和目标节点之间的连接是如何相关的。 节点可以与自身建立关系。&lt;/p&gt;
&lt;p&gt;关系：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;连接源节点和目标节点。&lt;/li&gt;
&lt;li&gt;具有方向（单向）。&lt;/li&gt;
&lt;li&gt;必须具有类型（一种类型），用于定义（分类）它是什么类型的关系。&lt;/li&gt;
&lt;li&gt;可以具有属性（键值对），用于进一步描述关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关系将节点组织成结构，使图可以类似于列表、树、地图或复合实体 - 它们中的任何一个都可以组合成更复杂、更丰富地互连的结构。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graph_example_relationship-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 5. 关系](插入图 5 的链接)&lt;/p&gt;
&lt;p&gt;关系类型：&lt;code&gt;ACTED_IN&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;属性是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;roles: [‘Forrest’]&lt;/li&gt;
&lt;li&gt;performance: 5&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;roles&lt;/code&gt; 属性具有一个数组值，其中包含一个项目（‘Forrest’）。&lt;/p&gt;
&lt;p&gt;可以使用 Cypher 使用以下查询创建关系：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE ()-[:ACTED_IN {roles: [&amp;#x27;Forrest&amp;#x27;], performance: 5}]-&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;您必须创建或引用源节点和目标节点才能创建关系。&lt;/p&gt;
&lt;p&gt;关系始终具有方向。 但是，在没有用的情况下，可以忽略方向。 这意味着没有必要在相反方向上添加重复关系，除非需要正确描述数据模型。&lt;/p&gt;
&lt;p&gt;一个节点可以与自身建立关系。 要表达 Tom Hanks 认识自己，可以表示为：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-nodes-and-rel-self-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 6. 与单个节点的关系](插入图 6 的链接)&lt;/p&gt;
&lt;h2&gt;关系类型&lt;/h2&gt;
&lt;p&gt;关系必须只有一个关系类型。&lt;/p&gt;
&lt;p&gt;下面是一个 &lt;code&gt;ACTED_IN&lt;/code&gt; 关系，其中 &lt;code&gt;Tom Hanks&lt;/code&gt; 节点作为源节点，&lt;code&gt;Forrest Gump&lt;/code&gt; 作为目标节点。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-nodes-and-rel-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 7. 关系类型](插入图 7 的链接)&lt;/p&gt;
&lt;p&gt;观察到 &lt;code&gt;Tom Hanks&lt;/code&gt; 节点具有传出关系，而 &lt;code&gt;Forrest Gump&lt;/code&gt; 节点具有传入关系。&lt;/p&gt;
&lt;h2&gt;属性&lt;/h2&gt;
&lt;p&gt;属性是键值对，用于在节点和关系上存储数据。&lt;/p&gt;
&lt;p&gt;属性的值部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以保存不同的数据类型，例如数字、字符串或布尔值。&lt;/li&gt;
&lt;li&gt;可以保存包含同类列表（数组），例如字符串、数字或布尔值。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例 1. 数字&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Example {a: 1, b: 3.14})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;属性 &lt;code&gt;a&lt;/code&gt; 的类型为整数，值为 &lt;code&gt;1&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;b&lt;/code&gt; 的类型为浮点数，值为 &lt;code&gt;3.14&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 2. 字符串和布尔值&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Example {c: &amp;#x27;This is an example string&amp;#x27;, d: true, e: false})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;属性 &lt;code&gt;c&lt;/code&gt; 的类型为字符串，值为 &lt;code&gt;&apos;This is an example string&apos;&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;d&lt;/code&gt; 的类型为布尔值，值为 &lt;code&gt;true&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;e&lt;/code&gt; 的类型为布尔值，值为 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 3. 列表&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-cypher&quot;&gt;&lt;code&gt;CREATE (:Example {f: [1, 2, 3], g: [2.71, 3.14], h: [&amp;#x27;abc&amp;#x27;, &amp;#x27;example&amp;#x27;], i: [true, true, false]})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;属性 &lt;code&gt;f&lt;/code&gt; 包含一个数组，其值为 &lt;code&gt;[1, 2, 3]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;g&lt;/code&gt; 包含一个数组，其值为 &lt;code&gt;[2.71, 3.14]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;h&lt;/code&gt; 包含一个数组，其值为 &lt;code&gt;[&apos;abc&apos;, &apos;example&apos;]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;属性 &lt;code&gt;i&lt;/code&gt; 包含一个数组，其值为 &lt;code&gt;[true, true, false]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;有关可用数据类型的完整描述，请参阅 [Cypher 手册 → 值和类型](链接到 Cypher 手册)。&lt;/p&gt;
&lt;h2&gt;遍历和路径&lt;/h2&gt;
&lt;p&gt;遍历是您查询图以查找问题答案的方式，例如：“我的朋友喜欢但​​我还没有拥有的音乐是什么？”，或者“如果此电源发生故障，哪些 Web 服务会受到影响？”。&lt;/p&gt;
&lt;p&gt;遍历图意味着按照某些规则通过跟随关系来访问节点。 在大多数情况下，仅访问图的子集。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 4. 路径匹配。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;要根据小型示例数据库找出 Tom Hanks 参演了哪些电影，遍历将从 &lt;code&gt;Tom Hanks&lt;/code&gt; 节点开始，跟随连接到该节点的任何 &lt;code&gt;ACTED_IN&lt;/code&gt; 关系，并以 &lt;code&gt;Movie&lt;/code&gt; 节点 &lt;code&gt;Forrest Gump&lt;/code&gt; 作为结果结束（参见黑线）：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-traversal-arr.svg&quot; alt=&quot;image&quot;&gt;
遍历结果可以作为长度为 1 的路径返回：
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-path-arr.svg&quot; alt=&quot;image&quot;&gt;
最短的可能路径的长度为零。 它包含一个节点，没有关系。&lt;/p&gt;
&lt;p&gt;仅包含单个节点的路径的长度为 0。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-path-zero-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 8. 长度为零的路径](插入图 8 的链接)&lt;/p&gt;
&lt;p&gt;包含一个关系的路径的长度为 1。
&lt;img src=&quot;https://neo4j.com/docs/getting-started/_images/graphdb-path-example-loop-arr.svg&quot; alt=&quot;image&quot;&gt;
![图 9. 长度为 1 的路径](插入图 9 的链接)&lt;/p&gt;
&lt;h2&gt;模式&lt;/h2&gt;
&lt;p&gt;Neo4j 中的模式是指索引和约束。&lt;/p&gt;
&lt;p&gt;Neo4j 通常被描述为“模式可选”，这意味着没有必要创建索引和约束。 您可以创建数据 - 节点、关系和属性 - 而无需预先定义模式。 可以在需要时引入索引和约束，以获得性能或建模优势。&lt;/p&gt;
&lt;h3&gt;索引&lt;/h3&gt;
&lt;p&gt;索引用于提高性能。 要查看如何使用索引的示例，请参阅使用索引。 有关如何在 Cypher 中使用索引的详细说明，请参阅 [Cypher 手册 → 索引](链接到 Cypher 手册中的索引部分)。&lt;/p&gt;
&lt;h3&gt;约束&lt;/h3&gt;
&lt;p&gt;约束用于确保数据符合域的规则。 要查看如何使用约束的示例，请参阅使用约束。 有关如何在 Cypher 中使用约束的详细说明，请参阅 [Cypher 手册 → 约束](链接到 Cypher 手册中的约束部分)。&lt;/p&gt;
&lt;h2&gt;命名约定&lt;/h2&gt;
&lt;p&gt;节点标签、关系类型和属性（键部分）区分大小写，这意味着例如，属性 &lt;code&gt;name&lt;/code&gt; 与属性 &lt;code&gt;Name&lt;/code&gt; 不同。&lt;/p&gt;
&lt;p&gt;建议使用以下命名约定：&lt;/p&gt;
&lt;p&gt;表 1. 命名约定&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;图实体&lt;/th&gt;
&lt;th&gt;推荐风格&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;节点标签&lt;/td&gt;
&lt;td&gt;驼峰式，以大写字符开头&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:VehicleOwner&lt;/code&gt; 而不是 &lt;code&gt;:vehicle_owner&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关系类型&lt;/td&gt;
&lt;td&gt;大写，使用下划线分隔单词&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:OWNS_VEHICLE&lt;/code&gt; 而不是 &lt;code&gt;:ownsVehicle&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;属性&lt;/td&gt;
&lt;td&gt;小驼峰式，以小写字符开头&lt;/td&gt;
&lt;td&gt;&lt;code&gt;firstName&lt;/code&gt; 而不是 &lt;code&gt;first_name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;有关精确的命名规则，请参阅 [Cypher 手册 → 命名规则和建议](链接到 Cypher 手册中的命名规则和建议部分)。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 07:10:07 GMT</pubDate></item><item><title>Neo4j官方教程：第2节，什么是图数据库</title><link>http://neo4j.com.cn/topic/67f4c2c9c181bb8b583a8a68</link><guid>http://neo4j.com.cn/topic/67f4c2c9c181bb8b583a8a68</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/graph-database/&quot;&gt;https://neo4j.com/docs/getting-started/graph-database/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;什么是图数据库&lt;/h1&gt;
&lt;p&gt;Neo4j 图数据库将数据存储为&lt;strong&gt;节点&lt;/strong&gt;、&lt;strong&gt;关系&lt;/strong&gt;和&lt;strong&gt;属性&lt;/strong&gt;，而不是存储在表或文档中。这意味着您可以像在白板上绘制想法一样组织数据。&lt;/p&gt;
&lt;p&gt;而且，由于图数据库不受预定义模型的限制，因此您可以在使用它们时采用更灵活的方法和策略。
&lt;img src=&quot;http://neo4j.6laohu.com/FhH8D-CxUrV9gOwZiASeNyjODCdq&quot; alt=&quot;image.png&quot;&gt;
图1。使用 Cypher 匹配模式和关系的可视化方式&lt;/p&gt;
&lt;h2&gt;工作原理&lt;/h2&gt;
&lt;p&gt;图数据库通过节点和关系进行结构化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;节点&lt;/strong&gt;是图中的实体，可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用&lt;strong&gt;标签&lt;/strong&gt;标记，表示它们在域中的不同角色（例如，&lt;em&gt;Person&lt;/em&gt;）。&lt;/li&gt;
&lt;li&gt;将任意数量的&lt;strong&gt;键值对&lt;/strong&gt;作为属性保存（例如，&lt;em&gt;name&lt;/em&gt;）。&lt;/li&gt;
&lt;li&gt;通过&lt;strong&gt;索引&lt;/strong&gt;和&lt;strong&gt;约束&lt;/strong&gt;绑定。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;关系&lt;/strong&gt;提供两个节点之间的命名连接（例如，&lt;em&gt;Person&lt;/em&gt; - &lt;em&gt;LOVES&lt;/em&gt; - &lt;em&gt;Person&lt;/em&gt;），它们：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;必须始终具有起始节点、结束节点和恰好一种类型。&lt;/li&gt;
&lt;li&gt;必须具有方向。&lt;/li&gt;
&lt;li&gt;可以像节点一样具有属性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;节点可以具有多种不同类型的关系，而不会牺牲性能。&lt;/p&gt;
&lt;p&gt;总之，节点和关系是一种高效且灵活的数据存储方式，因为它们允许您：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在大型图中创建深度和广度遍历。&lt;/li&gt;
&lt;li&gt;将数据库扩展到数十亿个节点。&lt;/li&gt;
&lt;li&gt;设计可以随时间调整的灵活属性图数据模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;为什么使用图数据库&lt;/h2&gt;
&lt;p&gt;项目通常处理大量复杂数据，图数据库可以成为强大的工具。&lt;/p&gt;
&lt;p&gt;还有其他方法可以将数据存储为对象和连接，例如关系数据库。但是，关系数据库使用计算成本高昂的 &lt;strong&gt;JOIN&lt;/strong&gt; 操作或交叉查找，而这些操作通常与僵硬的数据模型相关联。&lt;/p&gt;
&lt;p&gt;图数据库不使用 JOIN。相反，关系与数据元素（节点）一起以更灵活的格式本地存储，这允许优化数据遍历，并每秒访问数百万个连接。&lt;/p&gt;
&lt;p&gt;此外，许多日常挑战和任务都可以从图的角度来看待，因为它允许您：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;导航深层层次结构。&lt;/li&gt;
&lt;li&gt;查找远距离项目之间的隐藏连接。&lt;/li&gt;
&lt;li&gt;发现项目之间的相互关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;如何使用&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FrblM6nXHAYin7e1fBaT8xwWBYsV&quot; alt=&quot;image.png&quot;&gt;
无论是社交网络还是道路网络，所有网络都可以构建为相互关联的关系图。很多时候，项目的疑问和挑战都围绕元素之间的关系，而不是元素本身（例如，如何从 A 到 B，而不是 A 是什么，B 是什么）。因此，图可以应用于社会的许多领域和各种项目。&lt;/p&gt;
&lt;p&gt;Neo4j 目前被各种行业的&lt;strong&gt;初创公司&lt;/strong&gt;、&lt;strong&gt;教育机构&lt;/strong&gt;和&lt;strong&gt;大型企业&lt;/strong&gt;广泛使用，包括金融服务、政府、能源、技术、零售和制造业。图在帮助他们开发创新新技术、业务管理、洞察力和收入再生以及整体效率提升方面取得了成功。&lt;/p&gt;
&lt;p&gt;您可以在 Neo4j 的主网站上找到有关用例的更多信息。&lt;/p&gt;
&lt;h2&gt;继续学习&lt;/h2&gt;
&lt;p&gt;如果您想更好地深入了解图数据库，可以阅读有关&lt;a href&gt;图数据库概念&lt;/a&gt;的更多信息，或者在 &lt;a href&gt;Neo4j Fundamentals&lt;/a&gt; 上注册 GraphAcademy 课程。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 06:31:37 GMT</pubDate></item><item><title>Neo4j官方教程：第1节，Neo4j是什么</title><link>http://neo4j.com.cn/topic/67f4c1f2c181bb8b583a8a67</link><guid>http://neo4j.com.cn/topic/67f4c1f2c181bb8b583a8a67</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://neo4j.com.cn/topic/67f4cf91455186f56d9f412f&quot;&gt;教程目录&lt;/a&gt;
引自：&lt;a href=&quot;https://neo4j.com/docs/getting-started/whats-neo4j/&quot;&gt;https://neo4j.com/docs/getting-started/whats-neo4j/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Neo4j 简介&lt;/h1&gt;
&lt;p&gt;Neo4j 是一个原生图数据库，这意味着它在存储层实现了真正的图模型。它不是在其他技术之上使用“图抽象”，而是以您在白板上绘制想法的相同方式在Neo4j中存储数据。
&lt;img src=&quot;http://neo4j.6laohu.com/Fniu90v2Z45kbpiMqX5M0D1oVkNW&quot; alt=&quot;image.png&quot;&gt;
自2007年以来，Neo4j已经发展成为一个丰富的工具、应用程序和库的生态系统。该生态系统允许您以多种方式将图技术与您的工作环境集成，本文将对此进行描述。&lt;/p&gt;
&lt;p&gt;除了核心图之外，Neo4j还提供ACID事务、集群支持和运行时故障转移。&lt;/p&gt;
&lt;p&gt;Neo4j 使用Java和Scala编写。您可以在GitHub上查看源代码。&lt;/p&gt;
&lt;h2&gt;如何与Neo4j交互&lt;/h2&gt;
&lt;p&gt;Neo4j使用Cypher®，一种类似于SQL的声明式查询语言，但针对图进行了优化。其他数据库（如SAP HANA Graph）也通过openCypher项目使用相同的语言。&lt;/p&gt;
&lt;p&gt;另一种选择是使用库。Neo4j目前支持Java、JavaScript、.NET、Python、Go、GraphQL、Spring等。&lt;/p&gt;
&lt;h2&gt;创建Neo4j实例&lt;/h2&gt;
&lt;p&gt;部署数据库是探索Neo4j的第一步。从以下选项中选择适合您项目的部署方法：&lt;/p&gt;
&lt;h3&gt;完全托管的云服务&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Neo4j AuraDB&lt;/strong&gt;：一个完全托管的云服务，允许您直接从浏览器开始探索Neo4j。&lt;/li&gt;
&lt;li&gt;如果您是数据科学家，您可能还想查看&lt;strong&gt;Neo4j AuraDS&lt;/strong&gt;，并访问超过65种预调优的图算法。&lt;/li&gt;
&lt;li&gt;Neo4j Aura有免费和订阅版本。查看&lt;a href&gt;完整比较&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;自管理的云服务&lt;/h3&gt;
&lt;p&gt;您还可以在您选择的云平台上部署图数据库。Neo4j与Amazon Web Services（AWS）、Google Cloud（GCP）和Microsoft Azure兼容。&lt;/p&gt;
&lt;p&gt;对于自管理的云服务，您需要在本地安装Neo4j，或者如果您的项目不是生产环境，则使用Neo4j Desktop。&lt;/p&gt;
&lt;p&gt;Neo4j可在Linux、macOS和Windows上安装。&lt;/p&gt;
&lt;h3&gt;自管理的本地部署&lt;/h3&gt;
&lt;p&gt;如果您更喜欢使用本地部署：如果您不在生产环境中工作，请安装Neo4j Desktop，或者在本地安装Neo4j。&lt;/p&gt;
&lt;h3&gt;Docker上的Neo4j&lt;/h3&gt;
&lt;p&gt;Neo4j可以在Docker容器中运行。可以从DockerHub下载官方Neo4j映像，该映像为各种版本提供标准、随时可运行的Neo4j社区版和企业版软件包。它适用于macOS、Windows和Linux。&lt;/p&gt;
&lt;h3&gt;Kubernetes上的Neo4j&lt;/h3&gt;
&lt;p&gt;使用Neo4j Helm charts，您可以部署Neo4j的独立部署和集群部署在Kubernetes上，并使用适合最常见场景的配置选项。&lt;/p&gt;
&lt;p&gt;Neo4j具有免费和基于订阅的许可选项。阅读有关可用版本的更多信息。&lt;/p&gt;
&lt;h2&gt;处理数据&lt;/h2&gt;
&lt;p&gt;创建数据库后，您的学习可以根据您是想使用自己的数据还是使用Neo4j的示例数据集而采取不同的路径：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;自己的数据&lt;/strong&gt;：有几种方法可以将数据导入到Neo4j并对其进行建模，以获得更好的体验。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;示例数据集&lt;/strong&gt;：Aura和Neo4j浏览器都具有嵌入式指南，允许您创建示例数据集并开始查询。要访问它们，请使用Aura右上角的毕业帽图标，或在Neo4j浏览器中写入:guide。&lt;/li&gt;
&lt;li&gt;您还可以下载示例数据集，然后将其导入到您的实例中。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Neo4j工具&lt;/h2&gt;
&lt;p&gt;Neo4j有一系列工具，可用于各种目的，例如数据库管理、数据可视化等。您可以在工具中心查看所有产品。&lt;/p&gt;
&lt;h2&gt;支持的库&lt;/h2&gt;
&lt;p&gt;Neo4j支持几种最流行的查询语言，并提供专有库以获得定制体验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Neo4j图数据科学（GDS）库&lt;/strong&gt;：提供常见图算法和机器学习管道的实现，用于训练预测监督模型。您可以使用它们来解决图问题，例如预测缺失的关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对象图映射（OGM）库&lt;/strong&gt;：将图中的节点和关系映射到域模型中的对象和引用。您可以使用此资源开始跟踪更改，并最大限度地减少必要的更新和传递持久性（读取和更新对象的邻域）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;API&lt;/h2&gt;
&lt;p&gt;Neo4j目前提供三个专有API：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Neo4j HTTP API&lt;/strong&gt;：允许您通过HTTP请求针对Neo4j实例执行一系列Cypher语句。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更改数据捕获（CDC）API&lt;/strong&gt;：允许您实时捕获和跟踪数据库的更改，以及保持数据源最新。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neo4j查询API&lt;/strong&gt;：允许您使用Neo4j当前不支持的语言开发客户端应用程序。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在Neo4j Labs，您可以找到包括API、库和可视化工具在内的实验性项目。&lt;/p&gt;
&lt;h2&gt;继续学习&lt;/h2&gt;
&lt;p&gt;要了解有关图数据库是什么以及该技术背后的概念的更多信息，请继续阅读文档或浏览其他精选资源。&lt;/p&gt;
&lt;p&gt;您还可以在Neo4j社区网站上与其他Neo4j社区成员联系。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 06:28:02 GMT</pubDate></item><item><title>Docker 部署 Neo4j 方法</title><link>http://neo4j.com.cn/topic/67f49c24c181bb8b583a8a66</link><guid>http://neo4j.com.cn/topic/67f49c24c181bb8b583a8a66</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;h3&gt;1. 拉取 Neo4j 镜像&lt;/h3&gt;
&lt;p&gt;拉取镜像比较简单，用 Pull 就可以了。之后可以用 images查看。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;# 查看镜像
docker search neo4j
# 安装（指定版本的）neo4j
docker pull neo4j(:版本号)
# 查看镜像信息
docker images
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;2. 构建 Neo4j 容器&lt;/h3&gt;
&lt;p&gt;这部分主要参考了 docker安装部署neo4j (顺带一提，这真是我见过最好的博客园博客站了~~)。&lt;/p&gt;
&lt;p&gt;在任意文件夹构建四个子目录：data, logs, conf, import。&lt;/p&gt;
&lt;p&gt;随后可以按照下面的方法运行镜像，获取容器。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;docker run -d --name container_name \  &amp;#x2F;&amp;#x2F;-d表示容器后台运行 --name指定容器名字
    -p 7474:7474 -p 7687:7687 \  &amp;#x2F;&amp;#x2F;映射容器的端口号到宿主机的端口号
    -v &amp;#x2F;home&amp;#x2F;neo4j&amp;#x2F;data:&amp;#x2F;data \  &amp;#x2F;&amp;#x2F;把容器内的数据目录挂载到宿主机的对应目录下
    -v &amp;#x2F;home&amp;#x2F;neo4j&amp;#x2F;logs:&amp;#x2F;logs \  &amp;#x2F;&amp;#x2F;挂载日志目录
    -v &amp;#x2F;home&amp;#x2F;neo4j&amp;#x2F;conf:&amp;#x2F;var&amp;#x2F;lib&amp;#x2F;neo4j&amp;#x2F;conf   &amp;#x2F;&amp;#x2F;挂载配置目录
    -v &amp;#x2F;home&amp;#x2F;neo4j&amp;#x2F;import:&amp;#x2F;var&amp;#x2F;lib&amp;#x2F;neo4j&amp;#x2F;import \  &amp;#x2F;&amp;#x2F;挂载数据导入目录
    --env NEO4J_AUTH=neo4j&amp;#x2F;password \  &amp;#x2F;&amp;#x2F;设定数据库的名字的访问密码
    neo4j &amp;#x2F;&amp;#x2F;指定使用的镜像
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以直接运行的模板。其中，–name、NEO4J_AUTH、password 后面的内容都是可以修改的。地址也是可以修改的。&lt;/p&gt;
&lt;p&gt;下面的模板，我就将 NEO4J_AUTH 直接设置为了 none。这样登陆时就不需要输入密码了，很方便。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;# 模板
docker run -d --name neo4j -p 7474:7474 -p 7687:7687 -v &amp;#x2F;data2&amp;#x2F;software&amp;#x2F;neo4j_container&amp;#x2F;data:&amp;#x2F;data -v &amp;#x2F;data2&amp;#x2F;software&amp;#x2F;neo4j_container&amp;#x2F;logs:&amp;#x2F;logs -v &amp;#x2F;data2&amp;#x2F;software&amp;#x2F;neo4j_container&amp;#x2F;conf:&amp;#x2F;var&amp;#x2F;lib&amp;#x2F;neo4j&amp;#x2F;conf -v &amp;#x2F;data2&amp;#x2F;software&amp;#x2F;neo4j_container&amp;#x2F;import:&amp;#x2F;var&amp;#x2F;lib&amp;#x2F;neo4j&amp;#x2F;import --env NEO4J_AUTH=none neo4j
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;3. 远程配置&lt;/h3&gt;
&lt;p&gt;是否需要远程配置依据个人而定。我看到有的博客说，不进行远程配置就无法远程登陆。我这边测试没有这种情况。如果有的话，可以修改 neo4j.conf ，在下面加入：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;dbms.connector.bolt.listen_address=0.0.0.0:7687
dbms.connector.http.listen_address=0.0.0.0:7474
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;随后使用 restart 重启容器即可。&lt;/p&gt;
&lt;p&gt;防止防火墙屏蔽了端口，还可以查看防火墙信息。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;# 查看防火墙状态，如果是 inactive 就不用后续操作
sudo ufw status

# 如果防火墙为 active，就需要开放两个端口
sudo ufw allow 7474
sudo ufw allow 7687
sudo ufw reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 08 Apr 2025 03:46:44 GMT</pubDate></item><item><title>Neo4j 各个版本安装包下载点</title><link>http://neo4j.com.cn/topic/67ad4b328e65137814c5a995</link><guid>http://neo4j.com.cn/topic/67ad4b328e65137814c5a995</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;h2&gt;官方下载页&lt;/h2&gt;
&lt;p&gt;下载地址：&lt;a href=&quot;https://neo4j.com/deployment-center/&quot;&gt;https://neo4j.com/deployment-center/&lt;/a&gt;
打开后滚动到网页中部，如下位置选择版本下载
&lt;img src=&quot;http://neo4j.6laohu.com/Fvi7wYAyqeJ9ER9yy-lAScwjp6n0&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;s&gt;Neo4j 2025.01.0 Released 6 February 2025&lt;/s&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;s&gt;Neo4j 社区版&lt;/s&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;s&gt;Windows 版压缩包&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/neo4j-community-5.26.4-windows.zip&quot;&gt;neo4j-community-2025.01.0-windows.zip&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;s&gt;Linux / Mac 版压缩包&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/neo4j-community-5.26.4-unix.tar.gz&quot;&gt;neo4j-community-2025.01.0-unix.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;s&gt;Debian / Ubuntu 版安装包&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/deb/neo4j_5.26.4_all.deb&quot;&gt;neo4j_2025.01.0_all.deb&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;s&gt;Red Hat Linux 版安装包&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/rpm/neo4j-2025.03.0-1.noarch.rpm&quot;&gt;neo4j-2025.01.0-1.noarch.rpm&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;s&gt;Neo4j桌面安装版 Neo4j Desktop 1.6.1&lt;/s&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;s&gt;Windows 版 Neo4j Desktop (exe)&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/neo4j-desktop/win-offline/Neo4j%20Desktop%20Setup%201.6.1.exe&quot;&gt;Neo4j-Desktop-Setup-1.6.1.exe&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;&lt;s&gt;Mac 版 Neo4j Desktop (dmg)&lt;/s&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://dist.neo4j.org/neo4j-desktop/mac/Neo4j%20Desktop-1.6.1.dmg&quot;&gt;Neo4j-Desktop-1.6.1.dmg&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Thu, 13 Feb 2025 01:30:26 GMT</pubDate></item><item><title>用国产大模型+LangChain+Neo4j建立知识图谱 之四 开发实现局部和全局查询的自由对话Agent</title><link>http://neo4j.com.cn/topic/66ea47264b78504f7b274fec</link><guid>http://neo4j.com.cn/topic/66ea47264b78504f7b274fec</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;这是系列文章的第4篇:&lt;a href=&quot;https://zhuanlan.zhihu.com/p/718666439&quot;&gt;《用国产大模型+LangChain+Neo4j建立知识图谱 之四 开发实现局部和全局查询的自由对话Agent》&lt;/a&gt;。
要用LangChain写一个GraphRAG的APP，它要处理几种情况:&lt;/p&gt;
&lt;p&gt;1、有些问题不需要执行GraphRAG，LLM可以直接回答。比如打招呼的输入“你好”。&lt;/p&gt;
&lt;p&gt;2、有些问题需要执行GraphRAG的局部查询，在Neo4j知识图谱中查找答案，比如“唐僧和会说话的树讨论了什么？”这样的问题。&lt;/p&gt;
&lt;p&gt;3、有些问题需要执行GraphRAG的全局查询，在Neo4j知识图谱预先生成的社区摘要中查找答案，比如“唐僧的取经团队对遇到的妖怪是什么样的态度？”这样的问题。&lt;/p&gt;
&lt;p&gt;4、还需要支持有上下文的多轮对话，在多轮对话中上面3种问题和答案可能都有，交织在一起。&lt;/p&gt;
&lt;p&gt;5、最后用R Shiny APP UI去封装它们。&lt;/p&gt;
&lt;p&gt;最好的实现框架可能是LangChain的Agent，由Agent根据当前的上下文决定是否需要调用工具执行GraphRAG局部查询或全局查询，或者直接调LLM回答问题。这样有几个要求：&lt;/p&gt;
&lt;p&gt;1、LLM需要支持函数调用的功能，由Agent决定调用函数去执行GraphRAG局部查询或全局查询。并不是所有的国产大模型都支持函数调用功能，或者是在LangChain的集成中支持函数调用的功能。&lt;/p&gt;
&lt;p&gt;2、需要为GraphRAG局部查询与GraphRAG全局查询各写一个工具函数。&lt;/p&gt;
&lt;p&gt;3、需要写一个支持输出知识图谱检索溯源信息的自定义Agent。&lt;/p&gt;
&lt;p&gt;参阅LangChain文档《Conversational RAG》与LangGraph文档《 Agentic RAG》，这个工作看起来并不是那么简单，经过几天的努力还是完成了。&lt;/p&gt;
&lt;p&gt;体验地址：&lt;a href=&quot;https://jeanye.cn/shiny/users/jean/graphrag-kg/&quot;&gt;知识图谱GraphRAG聊天Agent&lt;/a&gt;。&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Wed, 18 Sep 2024 03:21:10 GMT</pubDate></item><item><title>用国产大模型+LangChain+Neo4j建立知识图谱 之二 实体工程：索引、合并与社区摘要</title><link>http://neo4j.com.cn/topic/66d97ecd4b78504f7b274fe3</link><guid>http://neo4j.com.cn/topic/66d97ecd4b78504f7b274fe3</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;这是系列文章的第二篇，对LLM从非结构化文本文档抽取的实体和关系作后期处理，以建立高质量的知识图谱。
Neo4j图数据库在这个过程中提供了非常好的支持，保证了构建知识图谱的效率和质量。
&lt;a href=&quot;https://zhuanlan.zhihu.com/p/716584792&quot;&gt;用国产大模型+LangChain+Neo4j建立知识图谱 之二 实体工程：索引、合并与社区摘要&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Thu, 05 Sep 2024 09:50:05 GMT</pubDate></item><item><title>用国产大模型+LangChain+Neo4j建立知识图谱 之一 实体关系提取与导入</title><link>http://neo4j.com.cn/topic/66cbca1ce7022dce3e5326ff</link><guid>http://neo4j.com.cn/topic/66cbca1ce7022dce3e5326ff</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;本篇以网络小说&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//dushu.baidu.com/pc/detail%3Fgid%3D4305630473%26data%3D%257B%2522scrollToCatalog%2522%3Atrue%257D&quot;&gt;《悟空传》的前7章&lt;/a&gt;来演示用国产LLM+LangChain+Neo4j（中文版）从非结构化的文本文档中构建知识图谱，开发支持&lt;a href=&quot;https://github.com/microsoft/graphrag&quot;&gt;微软GraphRAG&lt;/a&gt;论文中所述的全局查询与局部查询的具体过程。分为两个语料文件以演示从多文档数据集中构建知识图谱，第1个文本文件包含第1~4章，第2个文本文件包含第5~7章。从结构化的存量知识库中构建知识图谱会更简单一些，直接写Cypher查询语句灌入Neo4j就可以了。&lt;/p&gt;
&lt;p&gt;这个解决方案集成了Neo4j GraphRAG方案图数据库与工具链的优势，以及微软GrapRAG方案实体社区全局视野的优势，无缝连接各个主流的国产大模型，集各家之所长，是国内开发部署GraphRAG落地应用可行的高性价比解决方案。对于生产环境高负载高并发的落地应用来说，高性能图数据库与强大LLM模型的支撑是必不可少的，而LangChain这样的开发框架则有效的提高了构建、集成、开发、测试与部署落地应用等整个软件研发周期的效率，可以快速开发出应用原型，快速的迭代进化，快速的部署测试和应用。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/716089164&quot;&gt;《用国产大模型+LangChain+Neo4j建立知识图谱 之一 实体关系提取与导入》&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Mon, 26 Aug 2024 00:19:40 GMT</pubDate></item><item><title>server2008R2下运行neo4j遇到的问题</title><link>http://neo4j.com.cn/topic/66012a782925800d4d145855</link><guid>http://neo4j.com.cn/topic/66012a782925800d4d145855</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FgwmJR92uNPUUP4qV-DxbtUZlbsw&quot; alt=&quot;image.png&quot;&gt;
安装好以后启动进入选择应用数据路径的时候&amp;quot;confirm&amp;quot;按钮点击不了啦，导致应用启动不了。已经按照网上其他人说的增加path的环境变量：
C:\Windows\System32\wbem
C:\Windows\System32\WindowsPowerShell\v1.0
但是依然是这样，请问有遇到过这样的问题帮忙解决下。&lt;/p&gt;
&lt;/div&gt;</description><author>lxysoft</author><pubDate>Mon, 25 Mar 2024 07:40:40 GMT</pubDate></item><item><title>知识图谱构建和更新、Node Ebeddings的选择</title><link>http://neo4j.com.cn/topic/65eec7112925800d4d14584d</link><guid>http://neo4j.com.cn/topic/65eec7112925800d4d14584d</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;背景：
我目前想搭建一个基于neo4j的知识图谱，并基于图谱的GDS库生成Ebedding。这个图谱是需要更新的，对于更新的部分需要判断和目前搭建的图谱是否已经存在这个节点，或者有相似的节点存在。即：对于新来的node需要链接到现在的图谱中，并且生成Ebedding，与之前的Ebedding进行比较。&lt;/p&gt;
&lt;p&gt;我的问题是：
1、在搭建图谱时，节点的name是不是不会提供语义特征？或者是否有部分算法结合了语义特征和结构特征来生成最后的节点Ebeddding？
2、在更新了图谱之后，之前生成的Ebedding是否会跟着图更新一起更新？&lt;/p&gt;
&lt;p&gt;感谢各位大佬的帮助！&lt;/p&gt;
&lt;/div&gt;</description><author>wuhaosheng</author><pubDate>Mon, 11 Mar 2024 08:55:45 GMT</pubDate></item><item><title>图数据库应用场景归纳图</title><link>http://neo4j.com.cn/topic/65d1d690934e81d10fa16668</link><guid>http://neo4j.com.cn/topic/65d1d690934e81d10fa16668</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FkiDdSfs80uKZzsH2ZxvoMv4nBjU&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Sun, 18 Feb 2024 10:06:08 GMT</pubDate></item><item><title>Neo4j 插件APOC使用 后台任务和触发器</title><link>http://neo4j.com.cn/topic/65d172f1934e81d10fa16667</link><guid>http://neo4j.com.cn/topic/65d172f1934e81d10fa16667</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;查看后台任务&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CALL apoc.periodic.list();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;提交一个后台任务&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CALL apoc.periodic.submit(
 &amp;quot;create-person&amp;quot;,
 &amp;quot;CREATE (:Person {name: &amp;#x27;Michael Hunger&amp;#x27;})&amp;quot;
);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;多次执行的后台任务，每秒一次&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CREATE (:Counter {value: 10000});
 


CALL apoc.periodic.countdown(
 &amp;quot;decrement&amp;quot;,
 &amp;quot;MATCH (counter:Counter)
 SET counter.value = counter.value - 1
 RETURN counter.value as count&amp;quot;,
 1);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;触发器（4.4.5版本和5版本的不同）
数据发生变化时自动执行的cypher
需要在apoc.conf中配置如下：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;apoc.trigger.enabled=true
apoc.trigger.refresh=60000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;添加触发器
例子：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CREATE (:Counter {count:0})
CREATE (f:Foo);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;设置触发器，任何node被删除，Counter      的count属性+1&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CALL apoc.trigger.add(
 &amp;#x27;count-removals&amp;#x27;,
 &amp;#x27;MATCH (c:Counter)
 SET c.count = c.count + size([f IN $deletedNodes WHERE id(f) &amp;gt; 0])&amp;#x27;,
 {}
);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查看触发器：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CALL apoc.trigger.list();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;删除触发器&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-sql&quot;&gt;&lt;code&gt;CALL apoc.trigger.remove(&amp;quot;count-removals&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Sun, 18 Feb 2024 03:01:05 GMT</pubDate></item><item><title>分享一下我专著中Neo4j开发的一章：《第十七章 Neo4j图数据库应用开发》</title><link>http://neo4j.com.cn/topic/65b1ca83934e81d10fa16660</link><guid>http://neo4j.com.cn/topic/65b1ca83934e81d10fa16660</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;目录
第十七章	Neo4j图数据库应用开发
第一节	Neo4j数据加载
第二节	Python API连接Neo4j
第三节	Shiny 3D网络分析APP
第四节	开发Neo4j自定义函数
下载地址：
&lt;a href=&quot;https://jeanye.cn/book/Chapter17-Neo4j-Graph-APP-Development.docx&quot;&gt;第十七章	Neo4j图数据库应用开发&lt;/a&gt;
这是Neo4j Community 4.4.6+ Noe4j Graph Data Science 2.0.2上开发的。最近升级更新了Neo4j Community到5.15.0，Noe4j Graph Data Science到2.5.6，书需要点时间更新，先分享一下现在的版本。
有兴趣了解我的专著的朋友们可以读一下知乎上的这篇文章 &lt;a href=&quot;https://zhuanlan.zhihu.com/p/640437583&quot;&gt;《数里乾坤——开源节流 用R与Python玩转大数据》&lt;/a&gt;。
有兴趣交流探讨的朋友可以加Q或发mail到我的QQ:1793893070。&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Thu, 25 Jan 2024 02:42:11 GMT</pubDate></item><item><title>Neo4j Community 5.10.0+Open GDS 2.5.5最小树形图算法扩展插件</title><link>http://neo4j.com.cn/topic/65a8de5f934e81d10fa1665e</link><guid>http://neo4j.com.cn/topic/65a8de5f934e81d10fa1665e</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;详情请参阅我的知乎文章 &lt;a href=&quot;https://zhuanlan.zhihu.com/p/678160388&quot;&gt;《Neo4j Community 5.x+Open GDS 2.5最小树形图》&lt;/a&gt;，文末有下载链接。
欢迎联系交流探讨，QQ: 1793893070。&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Thu, 18 Jan 2024 08:16:31 GMT</pubDate></item><item><title>在Neo4j community 5.x+Neo4j Open GDS 2.5上开发扩展算法插件。</title><link>http://neo4j.com.cn/topic/65a5dc2626dc24635dc3ab39</link><guid>http://neo4j.com.cn/topic/65a5dc2626dc24635dc3ab39</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;在前几年Neo4j community 3.5+ Open GDS 1.4、1.6时，我在Open GDS上开发了扩展算法插件，增加了无向图上的K最小生成树及有向图上的朱刘算法最小树形图算法，可以用于主要供应链、销售连、产业链等分析。然后升级到Neo4j communnity 4.5+Open GDS 2.0，这两周研究升级到 Neo4j communinty 5.x+Open GDS 2.5，整理一下，分享给有兴趣了解的和研究的人们。Open GDS 2.5主要的变化是底层数据结构SpanningTree的存储结构增加了对long型下标超大图的支持，原来int型只支持 2,147,483,647以内的结点数，另外增加了存储结果边的权重。
具体请参阅我的两篇知乎文章：
1、 &lt;a href=&quot;https://zhuanlan.zhihu.com/p/677004443&quot;&gt;《更新Neo4j Open Graph Data Science扩展插件》&lt;/a&gt;
2、 &lt;a href=&quot;https://zhuanlan.zhihu.com/p/677746295&quot;&gt;《开发Neo4j Open GDS 2.5扩展插件算法和过程》&lt;/a&gt;
有兴趣了解研究的朋友们可以从我的个人网站上下载 &lt;a href=&quot;https://link.zhihu.com/?target=https%3A//jeanye.cn/tmp/Open-GDS-Extend-2.5.5.rar&quot;&gt;Eclipse Maven项目的源码&lt;/a&gt;，跑起来玩玩，它包括了无向图上K最小生成树的Prim算法实现，可以跟Open GDS及APOC、Cypher等完美的融合使用。
有兴趣交流的朋友可以在本社区交流群3群(622711500)里探讨，或加Q探讨：1793893070@qq.com。:)&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Tue, 16 Jan 2024 01:30:14 GMT</pubDate></item><item><title>有没有人玩过Neo4j Open Graph Data Science库?在Open GDS的基础上开发扩展算法插件。</title><link>http://neo4j.com.cn/topic/659bb61626dc24635dc3ab2a</link><guid>http://neo4j.com.cn/topic/659bb61626dc24635dc3ab2a</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;Hi,大家好，
我想在Eclipse里建个Maven项目，在Open Graph Data Science库的基础上开发一些扩展的算法，作为Plugin与GDS一起使用，之前的Neo4j community 4.4+Open GDS 2.0.2已经搞定了，现在想跟进一下Neo4j的版本升级，Neo4j community 5.10.0+ Open GDS 2.5.5, 建立 Eclipse Maven项目后，导入一些算法，比如spanningtree, 编译没有问题，算法的junit测试也没有问题，但调用算法的procedure的junit测试就不行，比如org.neo4j.gds.paths.spanningtree.SpanningTreeStatsProcTest，test-utils加载测试用的Neo4j实例时就出错了。详情请阅&lt;a href=&quot;https://community.neo4j.com/t/unable-to-run-open-graph-data-science-2-5-5-procedures-in-eclipse-maven-project/65642/1&quot;&gt;community.neo4j.com上的帖子&lt;/a&gt;， &lt;a href=&quot;https://github.com/neo4j/graph-data-science/issues/294&quot;&gt;Github Open GDS项目上的帖子&lt;/a&gt;。
我主要是要在Open GDS上开发无向图的K最小生成树及有向图的最小树形图算法，之前的研究可以看看我的几篇研究文章：
《Neo4j自定义过程开发之K最小生成树算法》：&lt;a href=&quot;https://www.meipian.cn/3gj6iqhz&quot;&gt;https://www.meipian.cn/3gj6iqhz&lt;/a&gt;
《在网络分析中使用Neo4j用户自定义函数与过程》：&lt;a href=&quot;https://www.meipian.cn/459u8wpz&quot;&gt;https://www.meipian.cn/459u8wpz&lt;/a&gt;
《机场航线环路分析》：&lt;a href=&quot;https://www.meipian.cn/451a6tnz&quot;&gt;https://www.meipian.cn/451a6tnz&lt;/a&gt;
请大家多多指教！
有向图入度方向的最小树形图
&lt;img src=&quot;http://neo4j.6laohu.com/FraEy_I_Emr-Z60oEL8vnDpjYgYm&quot; alt=&quot;arborescence-1.PNG&quot;&gt;
有向图出度方向的最小树形图
&lt;img src=&quot;http://neo4j.6laohu.com/FlljFC4zek-ced22eLPghW2x4jii&quot; alt=&quot;arborescence-2.PNG&quot;&gt;
Neo4j community 4.4.5+ Open GDS 2.0.2 Eclipse扩展算法插件项目
&lt;img src=&quot;http://neo4j.6laohu.com/Fi4an2-5GrHMX9lUZu01UI3NCBzN&quot; alt=&quot;Eclipse.PNG&quot;&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>icejean</author><pubDate>Mon, 08 Jan 2024 08:45:10 GMT</pubDate></item><item><title>使用java编写自定义函数 拓展Neo4j功能</title><link>http://neo4j.com.cn/topic/657111fe26dc24635dc3ab25</link><guid>http://neo4j.com.cn/topic/657111fe26dc24635dc3ab25</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;neo4j提供了丰富而强大的函数，可通过CALL dbms.procedures()查询
在一些复杂的应用场景中，neo4j自带的各种函数不能满足需求的时候，我们可以通过自定义函数去扩展和提升Neo4j的一些常用命令功能。
自定义函数的结果输出类型具体包括以下类型：
• java.lang.Boolean or boolean
• java.lang.Double or double
• java.lang.Long or long
• java.lang.Number
• java.lang.Object
• java.lang.String or string
• java.util.List
• java.util.Map
• org.neo4j.graphdb.Node
• org.neo4j.graphdb.Relationship
• org.neo4j.graphdb.Path
• org.neo4j.graphdb.spatial.Geometry
• org.neo4j.graphdb.spatial.Point
• Map&amp;lt;String, Object&amp;gt;
• List&lt;/p&gt;
&lt;p&gt;代码实现：
jar包依赖：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&amp;lt;properties&amp;gt;
		&amp;lt;neo4j.version&amp;gt;3.4.9&amp;lt;&amp;#x2F;neo4j.version&amp;gt;
		&amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;&amp;#x2F;project.build.sourceEncoding&amp;gt;
	&amp;lt;&amp;#x2F;properties&amp;gt;

	&amp;lt;dependencies&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.neo4j&amp;lt;&amp;#x2F;groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;neo4j&amp;lt;&amp;#x2F;artifactId&amp;gt;
			&amp;lt;version&amp;gt;${neo4j.version}&amp;lt;&amp;#x2F;version&amp;gt;
			&amp;lt;scope&amp;gt;provided&amp;lt;&amp;#x2F;scope&amp;gt;
		&amp;lt;&amp;#x2F;dependency&amp;gt;

		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.neo4j.test&amp;lt;&amp;#x2F;groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;neo4j-harness&amp;lt;&amp;#x2F;artifactId&amp;gt;
			&amp;lt;version&amp;gt;${neo4j.version}&amp;lt;&amp;#x2F;version&amp;gt;
			&amp;lt;scope&amp;gt;test&amp;lt;&amp;#x2F;scope&amp;gt;
		&amp;lt;&amp;#x2F;dependency&amp;gt;

		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.neo4j.driver&amp;lt;&amp;#x2F;groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;neo4j-java-driver&amp;lt;&amp;#x2F;artifactId&amp;gt;
			&amp;lt;version&amp;gt;1.4.2&amp;lt;&amp;#x2F;version&amp;gt;
			&amp;lt;scope&amp;gt;test&amp;lt;&amp;#x2F;scope&amp;gt;
		&amp;lt;&amp;#x2F;dependency&amp;gt;

		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;junit&amp;lt;&amp;#x2F;groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;junit&amp;lt;&amp;#x2F;artifactId&amp;gt;
			&amp;lt;version&amp;gt;4.12&amp;lt;&amp;#x2F;version&amp;gt;
			&amp;lt;scope&amp;gt;test&amp;lt;&amp;#x2F;scope&amp;gt;
		&amp;lt;&amp;#x2F;dependency&amp;gt;
	&amp;lt;&amp;#x2F;dependencies&amp;gt;

	&amp;lt;build&amp;gt;
		&amp;lt;plugins&amp;gt;
			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;&amp;#x2F;artifactId&amp;gt;
				&amp;lt;version&amp;gt;3.1&amp;lt;&amp;#x2F;version&amp;gt;
				&amp;lt;configuration&amp;gt;
					&amp;lt;!-- Neo4j Procedures require Java 8 --&amp;gt;
					&amp;lt;source&amp;gt;1.8&amp;lt;&amp;#x2F;source&amp;gt;
					&amp;lt;target&amp;gt;1.8&amp;lt;&amp;#x2F;target&amp;gt;
				&amp;lt;&amp;#x2F;configuration&amp;gt;
			&amp;lt;&amp;#x2F;plugin&amp;gt;
			&amp;lt;plugin&amp;gt;
				&amp;lt;artifactId&amp;gt;maven-shade-plugin&amp;lt;&amp;#x2F;artifactId&amp;gt;
				&amp;lt;version&amp;gt;2.4.3&amp;lt;&amp;#x2F;version&amp;gt;
			&amp;lt;&amp;#x2F;plugin&amp;gt;
		&amp;lt;&amp;#x2F;plugins&amp;gt;
	&amp;lt;&amp;#x2F;build&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;自定义函数：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-java&quot;&gt;&lt;code&gt;package com.zhbr.neo4j;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
import org.neo4j.procedure.UserFunction;

import java.util.*;

public class UserFunctions {
	
	@UserFunction(&amp;quot;my.hello&amp;quot;)
	@Description(&amp;quot;问候&amp;quot;)
	public String hello(@Name(&amp;quot;name&amp;quot;) String name) {
		return &amp;quot;Hello &amp;quot;+name;
	}

	@UserFunction(&amp;quot;my.add&amp;quot;)
	@Description(&amp;quot;加法&amp;quot;)
	public double add(@Name(&amp;quot;i&amp;quot;) double i,@Name(&amp;quot;y&amp;quot;) double y) {
		return i+y;
	}

	@UserFunction(&amp;quot;my.compare&amp;quot;)
	@Description(&amp;quot;比较两个节点的属性是否相同&amp;quot;)
	public Boolean compare(@Name(&amp;quot;node1&amp;quot;) Node i, @Name(&amp;quot;node2&amp;quot;) Node y) {
		String i_ywxtmc = (String) i.getProperty(&amp;quot;ywxtmc&amp;quot;);
		String y_ywxtmc = (String) y.getProperty(&amp;quot;ywxtmc&amp;quot;);
		if (i_ywxtmc.equals(y_ywxtmc)){
			return true;
		}
		return false;
	}

	@UserFunction(&amp;quot;my.recommendation&amp;quot;)
	@Description(&amp;quot;写的乱七八糟的推荐算法&amp;quot;)
	public String recommendation(@Name(&amp;quot;node&amp;quot;) Node node){
		ArrayList&amp;lt;Integer&amp;gt; maxCount = new ArrayList&amp;lt;&amp;gt;();

		ArrayList&amp;lt;String&amp;gt; moviesBox = new ArrayList&amp;lt;&amp;gt;();

		Iterable&amp;lt;Relationship&amp;gt; relationships = node.getRelationships();
		for (Relationship relationship : relationships){
			Node nodes = relationship.getEndNode();

			String likeMovies = (String) nodes.getProperty(&amp;quot;name&amp;quot;);
			moviesBox.add(likeMovies);
		}

		Map&amp;lt;String, Integer&amp;gt; listElements = frequencyOfListElements(moviesBox);
		for (Map.Entry&amp;lt;String, Integer&amp;gt; entry : listElements.entrySet()){
			int value = entry.getValue().intValue();
			maxCount.add(value);
		}

		Integer max = Collections.max(maxCount);
		String key = getKey(listElements, max);

		return key;
	}

	&amp;#x2F;**
	 * java统计List集合中每个元素出现的次数
	 * 例如frequencyOfListElements([&amp;quot;111&amp;quot;,&amp;quot;111&amp;quot;,&amp;quot;222&amp;quot;])
	 *  -&amp;gt;
	 * 则返回Map {&amp;quot;111&amp;quot;=2,&amp;quot;222&amp;quot;=1}
	 * @param items
	 * @return  Map&amp;lt;String,Integer&amp;gt;
	 * @author wuqx
	 *&amp;#x2F;
	public Map&amp;lt;String,Integer&amp;gt; frequencyOfListElements(List&amp;lt;String&amp;gt; items ) {
		if (items == null || items.size() == 0) return null;
		Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;String, Integer&amp;gt;();
		for (String temp : items) {
			Integer count = map.get(temp);
			map.put(temp, (count == null) ? 1 : count + 1);
		}
		return map;
	}

	&amp;#x2F;**
	 * 根据value找key
	 * @param map
	 * @param value
	 * @return
	 *&amp;#x2F;
	private String getKey(Map&amp;lt;String, Integer&amp;gt; map, Object value) {
		String key = &amp;quot;&amp;quot;;
		for (Map.Entry&amp;lt;String, Integer&amp;gt; entry : map.entrySet()) {
			if (value.equals(entry.getValue())) {
				key = entry.getKey();
				continue;
			}
		}
		return key;
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;代码测试：&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-java&quot;&gt;&lt;code&gt;package com.zhbr.neo4j;

import org.junit.Rule;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Result;
import org.neo4j.harness.junit.Neo4jRule;

public class UserFunctionTest {
	
	@Rule
	public Neo4jRule neo4j = new Neo4jRule().withFunction(UserFunctions.class);

	@Test
	public void testGreeting() {
		GraphDatabaseService db = neo4j.getGraphDatabaseService();
		Result result = db.execute(&amp;quot;return my.hello(&amp;#x27;world&amp;#x27;) as res&amp;quot;);
		System.out.println(result.next().get(&amp;quot;res&amp;quot;).toString());

		Result result1 = db.execute(&amp;quot;return my.add(1,2) as res&amp;quot;);
		System.out.println(result1.next().get(&amp;quot;res&amp;quot;).toString());
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FvwCpJ8NnSVimKedFMQJGC5ov4Pq&quot; alt=&quot;image.png&quot;&gt;
将jar包添加到neo4j
maven package后会在target目录下生成jar包，将jar包放到neo4j项目的plugin目录下，重启neo4j即可&lt;/p&gt;
&lt;p&gt;测试
&lt;img src=&quot;http://neo4j.6laohu.com/FsvIuHgmXs8rwoaQ24SWcwpT689E&quot; alt=&quot;image.png&quot;&gt;
&lt;img src=&quot;http://neo4j.6laohu.com/FnFTLDhYLs1_EeSYxo7wlnyBBN1N&quot; alt=&quot;image.png&quot;&gt;
&lt;img src=&quot;http://neo4j.6laohu.com/FvChOK9NR8A9bs4flIf8GN2Y7us2&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;本文参考：
&lt;a href=&quot;https://blog.csdn.net/yuanyk1222/article/details/94558980&quot;&gt;https://blog.csdn.net/yuanyk1222/article/details/94558980&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Thu, 07 Dec 2023 00:29:50 GMT</pubDate></item><item><title>NEO4J空间索引</title><link>http://neo4j.com.cn/topic/654acf2d26dc24635dc3ab18</link><guid>http://neo4j.com.cn/topic/654acf2d26dc24635dc3ab18</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;Neo4j空间索引可以对数据进行空间索引，例如在指定区域内以某个感兴趣的点作为起始，搜索指定距离内其它感兴趣的点。可以方便地将空间索引的节点数据与已有图数据结合分析。&lt;/p&gt;
&lt;p&gt;1、创建图层&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.addPointLayer(&amp;#x27;geom&amp;#x27;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FmzskAzsQe3JV6tNFxWlX-p9HoWZ&quot; alt=&quot;image.png&quot;&gt;
2、查看已经创建的图层列表&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.layers()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FnTGPUNaJmgI__dwx4KYG17lgxBq&quot; alt=&quot;image.png&quot;&gt;
3、建立空间点并将新创建的点加入到geom图层中&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;MERGE (n:Node {longitude:15.2,latitude:60.1}) WITH n 
CALL spatial.addNode(&amp;#x27;geom&amp;#x27;,n) YIELD node RETURN node
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FmZndCQ6QeE_hW2aCM_EuHAAASrM&quot; alt=&quot;image.png&quot;&gt;
4、查询维度在60.0到60.2之间，经度在15.0到15.3之间的空间点&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.bbox(&amp;#x27;geom&amp;#x27;,{longitude:15.0,latitude:60.0},{longitude:15.3,latitude:60.2}) YIELD node RETURN node
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FkZy7ZkSQ7Vph8zk0cbuEibGCDHs&quot; alt=&quot;image.png&quot;&gt;
5、导入全国公路shp文件
数据下载地址 &lt;a href=&quot;https://malagis.com/gis-data-china-road-shp.html&quot;&gt;https://malagis.com/gis-data-china-road-shp.html&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&amp;#x2F;&amp;#x2F; 将*.shp,*.dbf,*.shx文件移动到neo4j安装根目录下
CALL spatial.addWKTLayer(&amp;#x27;layer_roads&amp;#x27;,&amp;#x27;geometry&amp;#x27;)
CALL spatial.importShapefileToLayer(&amp;#x27;layer_roads&amp;#x27;,&amp;#x27;roa_4m.shp&amp;#x27;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;6、查询一个矩形内的图形语句&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.bbox(&amp;#x27;layer_roads&amp;#x27;,{longitude:14.0,latitude:60.0},{longitude:19.3,latitude:81.0}) YIELD node RETURN node.name as name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;7、查询一个多边形内的点&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;WITH &amp;quot;POLYGON((15.3 60.0,15.3 62.0,15.2 60.2,15.4 65.0))&amp;quot; as  polygon
CALL spatial.intersects(&amp;#x27;layer_roads&amp;#x27;, polygon) YIELD node RETURN node.name as name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;8、WithinDistance - 查询点周边distance（0.1km）以内的点&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.withinDistance(&amp;#x27;geom&amp;#x27;,{longitude:15.2,latitude:60.1},0.1) YIELD node RETURN node LIMIT 10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FtSGgjKk96XfiDZlcRgvh9nfJP4M&quot; alt=&quot;image.png&quot;&gt;
9、批量节点构建空间索引&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL spatial.addPointLayer(&amp;#x27;geom&amp;#x27;)
UNWIND [{name:&amp;#x27;a&amp;#x27;,latitude:60.1,longitude:15.2},{name:&amp;#x27;b&amp;#x27;,latitude:60.3,longitude:15.5}] as point CREATE (n:Node) SET n += point WITH n 
CALL spatial.addNode(&amp;#x27;geom&amp;#x27;,n) YIELD node RETURN node.name as name
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;neo4j-spatial-plugin downloa &lt;a href=&quot;https://github.com/neo4j-contrib/spatial/releases&quot;&gt;https://github.com/neo4j-contrib/spatial/releases&lt;/a&gt;
neo4j根据经纬度计算两点之间的距离&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Tue, 07 Nov 2023 23:58:37 GMT</pubDate></item><item><title>Neo4j有哪些版本</title><link>http://neo4j.com.cn/topic/65497b1e26dc24635dc3ab17</link><guid>http://neo4j.com.cn/topic/65497b1e26dc24635dc3ab17</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;Neo4j图数据库是全球领先的图数据库平台软件，并同时为开源社区和商业应用提供不同版本的软件。&lt;/p&gt;
&lt;p&gt;Neo4j的主要版本介绍如下：&lt;/p&gt;
&lt;p&gt;1）Neo4j Community 社区版
社区版是完全开源（Java）的软件项目，遵从GPL v3开源协议。其包含Neo4j原生图数据库引擎、Cypher分析编译器、存储管理、Neo4j Browser、cypher-shell命令行工具。Neo4j是纯Java应用，可以运行在多数操作系统上。&lt;/p&gt;
&lt;p&gt;Neo4j的开源版和企业版在每次版本更新中同时发布。&lt;/p&gt;
&lt;p&gt;共享地址：&lt;a href=&quot;https://github.com/neo4j/neo4j&quot;&gt;https://github.com/neo4j/neo4j&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在线社区支持：&lt;a href=&quot;http://stackoverflow.com&quot;&gt;stackoverflow.com&lt;/a&gt;, &lt;a href=&quot;http://community.neo4j.com&quot;&gt;http://community.neo4j.com&lt;/a&gt;，&lt;a href=&quot;http://neo4j.com.cn&quot;&gt;http://neo4j.com.cn&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;2）Neo4j Enterprise 企业版
Neo4j企业版是商业化的图数据库软件。在功能和技术实现方面，它和社区版主要区别在于：&lt;/p&gt;
&lt;p&gt;a. 支持数据库集群(因果集群)，提供高可用性和数据冗余；
b. 支持对超大规模数据存储的支持：&amp;gt;340亿节点，&amp;gt;340亿边；
c. 支持对更多CPU内核的查询执行优化；
d. 提供在线备份等DBA功能；
e. 支持其他组件，例如可视化工具Bloom&lt;/p&gt;
&lt;p&gt;3）Neo4j Desktop
Neo4j Desktop是安装在Windows或Mac计算机上的应用软件，它包含试用的企业版数据库引擎，可以创建本地的图数据库；它也支持到远端数据库的连接。Neo4j Desktop 还包含一个应用管理器，可以方便地下载和安装Neo4j扩展应用，例如ETL、Bloom等。&lt;/p&gt;
&lt;p&gt;Neo4j的数据库扩展，例如APOC、ALGO等，可以在所有Neo4j版本上安装和试用。&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 06 Nov 2023 23:47:42 GMT</pubDate></item><item><title>Neo4j图数据库包含哪些功能和组件</title><link>http://neo4j.com.cn/topic/65497afd26dc24635dc3ab16</link><guid>http://neo4j.com.cn/topic/65497afd26dc24635dc3ab16</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;图数据库(Graph Database)是以图模型存储实体数据(称为“节点”、“顶点”、node)、实体之间关系(称为“关系”、“边”、relationship/edge)、以及实体和关系上属性(property)的数据库。&lt;/p&gt;
&lt;p&gt;图数据库是非SQL(NoSQL) 数据库的一种，它基于数学和计算机科学中的“图论”。图数据库内置的图模型能更灵活、准确地描述现实世界，并提供近似与数据规模无关的查询性能。&lt;/p&gt;
&lt;p&gt;Neo4j企业版图数据库(版本3.5.*)平台包含下面的功能组件：
&lt;img src=&quot;http://neo4j.6laohu.com/FvDUpgxJp6ylttHnu6MP1xPeZlat&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 06 Nov 2023 23:47:09 GMT</pubDate></item><item><title>Neo4j因果集群路由策略详解及驱动访问</title><link>http://neo4j.com.cn/topic/654979e926dc24635dc3ab15</link><guid>http://neo4j.com.cn/topic/654979e926dc24635dc3ab15</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;Neo4j的使用和大多数数据库一样，如果您只想查询，这很简单。使用驱动程序，创建连接，提交查询并返回结果，如此简单！
如果您正在使用数据库集群，那么要做的事情不止这些。首先，数据库实例不是单个节点，而是由多台服务器组成。本文将探讨Neo4j集群如何工作以及Neo4j驱动程序如何执行查询。
&lt;img src=&quot;http://neo4j.6laohu.com/FnWPtThqR16WD6t4ngGeehP6heeF&quot; alt=&quot;image.png&quot;&gt;
如何在Neo4j上运行查询
在讨论驱动程序之前，我们需要简单说明Neo4j集群如何工作以及集群角色是什么，这将有助于帮您了解驱动访问。&lt;/p&gt;
&lt;p&gt;1、Neo4j因果集群
一个集群由3个或更多Neo4j实例组成，它们使用共识协议（RAFT）彼此通信，以提供容错和高可用性。在Neo4j集群中，每个实例都有完整数据库副本（该图未分片）。集群中的每个节点都有一个“role”：LEADER或者FOLLOWER。
&lt;img src=&quot;http://neo4j.6laohu.com/Fv5Pva3ct1w7VYGmrSgDCONjdfw7&quot; alt=&quot;image.png&quot;&gt;
1.1 集群角色
LEADER 负责协调集群并接受所有写入，FOLLOWER 扩展集群的读负载能力，并提供高可用性的数据。如果集群中一个节点发生故障，并且仍然拥有多数席位，则其可以继续处理读和写操作。如果失去了多数席位，那么集群只能读，并且不再具有 LEADER。
另外，集群可以增加任意数量的只读副本（READ REPLICA），它们是集群核心节点的只读副本，用于扩展查询负载。它们不是正式的集群成员，而是“tag alone”副本，可从集群同步事务。&lt;/p&gt;
&lt;p&gt;1.2 拓扑变化
在集群的生命周期中，集群角色是临时的，而不是您配置的角色。假设您有机器 A（LEADER）、B和C。如果 A 发生故障，将在其余节点（B和C）间选举一个新的领导者。当 A 重新启动时，稍后，它将重新加入集群，但可能是 FOLLOWER。因此，角色可以在集群的整个生命周期中进行更改。集群正常运行，出于各种其他原因，集群可以选举新的LEADER ，因此，就角色本身而言，不必担心引起任何变化。
Neo4j使用RAFT共识算法来控制集群。&lt;/p&gt;
&lt;p&gt;2、Neo4j驱动程序
驱动程序API包括以下四个关键部分，以下概念适用于Neo4j集群和单实例。
&lt;img src=&quot;http://neo4j.6laohu.com/FlxxnDIQh6RtgisvPB9x9OnvNuIy&quot; alt=&quot;image.png&quot;&gt;
Neo4j驱动程序API的核心部分&lt;/p&gt;
&lt;p&gt;但是，在集群中，由于我们正在与一组计算机通信，因此如何执行事务以及将事务转到何处，是“路由驱动程序”控制执行的。&lt;/p&gt;
&lt;p&gt;3、路由驱动程序
当您使用某种 Neo4j驱动程序（Java，Javascript，Python，.Net和Go）时，会有使用 bolt+routing 协议的选项。例如，您可以连接到bolt+routing://neo4j.myhost.com。
注意：
对于集群，设置一个包含多个 A 项的 DNS 记录，每个 A 项都指向集群成员。
这样，所有客户端都可以连接到相同的 DNS 地址，但是根据集群状态和运行状况，可以将不同的计算机作为入口点。或者可以直接连接到服务器成员的 IP 地址，但是这种方式在拓扑更改时更加灵活。
如果要连接到任何单个主机或地址，则驱动程序将为您处理路由。驱动程序将首先检查数据库是否具有路由功能，如果是，则将进行读取，以保存可用读取和写入服务的全部或部分快照。在那之后，除非驱动程序与集群失去联系并且必须重新初始化路由，否则将不使用初始主机地址。&lt;/p&gt;
&lt;p&gt;3.1 路由表
该路由表包含提供的服务器列表ROUTE，READ和WRITE功能。该路由信息被认为是volatile，并且会定期刷新。
&lt;img src=&quot;http://neo4j.6laohu.com/Fq4mrAphSREknDtBBhfC59WWFZ6H&quot; alt=&quot;image.png&quot;&gt;
Neo4j集群路由表&lt;/p&gt;
&lt;p&gt;驱动程序会定期刷新此信息，因为集群拓扑可能会根据 runtime 事件（例如计算机故障）而发生变化。通常，WRITE 节点将成为 LEADER ，而 READ 节点将成为集群或只读副本中的 FOLLOWER。
重要提示:
只读副本不参与集群拓扑管理，因此它们不提供路由表，仅核心节点提供路由表。这可能在Neo4j的后续发行版中有所更改。
如果您想自己尝试一下，只需Neo4j集群任一实例执行以下语句：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;CALL dbms.cluster.routing.getRoutingTable({})
YIELD ttl, servers
UNWIND servers as server
RETURN ttl, server.role, server.addresses;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/Fnl2y3zSuRDoXAJFPq_6A3zDFxqW&quot; alt=&quot;image.png&quot;&gt;
Neo4j集群的路由表&lt;/p&gt;
&lt;p&gt;这个特定的 Cypher 查询仅供内部使用，并且Neo4j的将来版本可能会更改，因此不要在其中编写代码，但可以使您了解驱动程序的实际功能。&lt;/p&gt;
&lt;p&gt;3.2 广播地址
路由表例子中的那些地址从何而来？用户在neo4j.conf文件中配置 dbms.connector.bolt.advertised_address 。通过这种方式，Neo4j知道将哪个地址发布到可以联系到它的外部。（配置参考）
重要提示：
客户端使用广播地址访问集群，该配置非常重要，neo4j.conf显式设置。
请确保它是可以由clients解析（而不是内网地址，比如192.168.0.5)。一个常见的错误与Neo4j的连接没有配置，或将其设置为内部私有地址，外部Internet上的客户端无法连接，因为它们无法弄清楚如何访问您的数据库！&lt;/p&gt;
&lt;p&gt;4、连接管理
一旦建立了路由表，驱动程序就可以管理与集群中所有不同计算机的连接池。用户看到的通常只是会话的创建，以及从这些会话中运行查询。驱动程序内部的实际内容看起来更像是与一组计算机（A，B等）的连接池。会话只是根据需要连接并执行查询。
&lt;img src=&quot;http://neo4j.6laohu.com/FgI9Ex_i6axKivBQ4GiFXsqKKz0W&quot; alt=&quot;image.png&quot;&gt;
Neo4j驱动程序连接管理&lt;/p&gt;
&lt;p&gt;这些连接是分开处理的，因此，如果服务器 A 消失并且所有这些连接最终都要超时，则您在会话级别上不必一定知道。会话仍可以访问其他连接，并且您的应用程序可以继续运行。正在执行的语句将失败，并由驱动程序自动重试。
用户使用会话执行查询。会话是要创建的便宜对象（与连接不同，它的建立成本很高）。会话还提供了一种因果一致性的方式将工作链链接在一起的逻辑结构，这意味着您可以执行一系列事务，后续事务始终读取同一会话中较早事务所做的写操作。&lt;/p&gt;
&lt;p&gt;4.1 路由查询
现在，假设您的驱动程序将查询发送到数据库，我将以JavaScript为例，此方法适用于任何语言。
我们要做的第一件事是从驱动程序中创建会话。然后，我们使用该会话执行查询。&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;const session = driver.session();
session.readTransaction(tx =&amp;gt; tx.run(&amp;#x27;MATCH (n) RETURN count(n) as value&amp;#x27;))
.then(results =&amp;gt; {
console.log(results.records[0].get(&amp;#x27;value&amp;#x27;));
})
.finally(() =&amp;gt; session.close());
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;驱动如何知道将查询发送到哪里？在此代码示例中，我们使用了显式事务，这意味着我们告诉驱动程序我们正在执行readTransaction。我们获得了一个txTransaction对象，并以此运行查询。因为具有路由表，并且知道您正在读取，所以它最终可能会将此查询发送到具有该 READ 角色的节点之一。如果执行写事务，它将被发送到路由表的 WRITE 节点（通常是集群 LEADER）。
如果路由驱动程序在发送查询的位置上有多种选择，则使用“ least connected ”策略，这有助于避免意外路由到当前太忙而无法及时响应的服务器。
&lt;img src=&quot;http://neo4j.6laohu.com/FsKm3wHCVpDPf_ViTTIMPlz57m1V&quot; alt=&quot;image.png&quot;&gt;
最小关联策略&lt;/p&gt;
&lt;p&gt;4.2 自动提交事务
如果您不使用显式事务怎么办？您可以参照下面的方式：&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;const session = driver.session();
session.run( tx =&amp;gt; tx.run(&amp;#x27;CALL library.myProcedure()&amp;#x27;))
.then(results =&amp;gt; {
console.log(results.records[0].get(&amp;#x27;value&amp;#x27;));
})
.finally(() =&amp;gt; session.close());
&amp;#96;&amp;#96;
在这种情况下，驱动程序无法知道读或者写操作，而将事务直接发送给 LEADER 。这样，即使您没有告诉它是需要读还是写，事务也应该成功。
重要提示：
Neo4j驱动程序不会解析您的Cypher来确定您正在读取还是正在写入。
始终使用显式事务来告诉驱动是读还是写。这有助于其有效地路由查询，并从集群中获得最佳利用率。如果您从未使用过显式事务，则可能会将所有查询负载发送给 LEADER，对其进行轰炸，同时使集群中的其它计算机保持空闲状态。

5、结论
在集群部署中，Neo4j利用 bolt+routing 协议让客户端动态发现集群拓扑，并使用“least connected”策略将查询路由到集群中的计算机。所有这些对您都是透明的，因此在用户级别，您将看到的是创建会话，运行查询和使用结果。
要从此设置中获得最大收益，需要对它的工作方式有所了解，并且需要牢记的最重要部分如下：
1）正确配置广播地址
2）在驱动程序代码中使用显式事务调用
3）DNS配置尽可能创建单个DNS记录，所有客户端使用该记录访问集群任何节点

有关Neo4j路由驱动程序的更多信息，请参阅Neo4j驱动程序手册 和原文。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><author>pangguoming</author><pubDate>Mon, 06 Nov 2023 23:42:33 GMT</pubDate></item><item><title>轻量级图数据库NeuroDB被 dbdb.io 收录</title><link>http://neo4j.com.cn/topic/6531f3e926dc24635dc3ab0a</link><guid>http://neo4j.com.cn/topic/6531f3e926dc24635dc3ab0a</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/Fgxh8AQc77e7vDCcy1bYcjemfPJg&quot; alt=&quot;b15e9c3599184763158053dde4349ed.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://neo4j.6laohu.com/FoeFPe6P97k4QP8WiyP6IcAJhjpe&quot; alt=&quot;9e4e5bd8399a81c47c760f5d9b70bbc.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;NeuroDB被 &lt;a href=&quot;http://dbdb.io&quot;&gt;dbdb.io&lt;/a&gt; 收录  &lt;a href=&quot;https://dbdb.io/db/neurodb&quot;&gt;https://dbdb.io/db/neurodb&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description><author>pangguoming</author><pubDate>Fri, 20 Oct 2023 03:28:41 GMT</pubDate></item><item><title>使用neovis.js时无法显示关系</title><link>http://neo4j.com.cn/topic/653125e989f0622c1d878410</link><guid>http://neo4j.com.cn/topic/653125e989f0622c1d878410</guid><description>&lt;div class=&quot;markdown-text&quot;&gt;&lt;p&gt;我在使用neovis.js时,发现关系无法显示出来，如下图所示&lt;img src=&quot;http://neo4j.6laohu.com/FgB8DOGTgh1iWprF4r635ENNafYI&quot; alt=&quot;image.png&quot;&gt;，以下是我的配置
var config = {
containerId: “viz”,
neo4j: {
serverUrl: “bolt://localhost:7687”,
serverUser: “neo4j”,
serverPassword: “csu123”
},
labels: {
Project: {
label: “name”,
value: “pagerank”,
group: “community”
},
Person:{
label: “name”,
value: “pagerank”,
group: “community”
},
Bidder:{
label: “name”,
value: “pagerank”,
group: “community”
},
Agent:{
label: “name”,
value: “pagerank”,
group: “community”
}
},
relationships: {
AGENT_OF: {
value: ‘weight’,
caption: true,
label: “name”,
}
},
visConfig: {
nodes: {
shape: ‘square’
},
edges: {&lt;br&gt;
arrows: {
to: {
enabled: true,
type: “arrow”,
},
},
},
},
initialCypher: &lt;code&gt;MATCH (n{name:&amp;quot;项目21479&amp;quot;})-[r1]-(m)-[r2]-(o),(a)-[r3]-(n)RETURN n,r1,m,r2,a,r3&lt;/code&gt;
};
		我想要知道如何才能将关系显示出来，有大佬知道吗&lt;/p&gt;
&lt;/div&gt;</description><author>csu_fw</author><pubDate>Thu, 19 Oct 2023 12:49:45 GMT</pubDate></item></channel></rss>