AI Agent Harness Engineering 的长期记忆构建:图数据库 Neo4j 在关系抽取中的应用实战
AI Agent Harness Engineering 的长期记忆构建:图数据库 Neo4j 在关系抽取中的应用实战
一、引言 (Introduction)
1.1 钩子 (The Hook)
你有没有遇到过这样的AI对话场景?前一秒你兴致勃勃地和GPT-4o Mini聊完你那只叫“毛球”的橘猫上周三在公司茶水间打翻同事保温杯的糗事——甚至精确到了同事是“行政部的Lisa Wang”、保温杯是“薄荷绿的虎牌316L款”、打翻后洒的是“39度半的冷萃茉莉乌龙配柠檬片”,毛球还“舔了一口洒在Lisa刚打印好的季度预算表上的茶渍”,Lisa无奈之下还“给了毛球一条昨天剩下的原味皇家奶糕猫条”——可仅仅过了10分钟,你再问它:“毛球上周和谁互动了?”,它要么一脸茫然地反问“毛球是谁?是你刚才提到的虚拟助手角色吗?”,要么只给出一个干巴巴的、来自知识库的通用回答“猫通常会和主人、其他宠物或食物互动”。
更气人的是,如果你试图用更长的上下文窗口(比如Claude 3 Opus的200K甚至GPT-4o的128K)来“硬塞”这些信息,不仅会让每次对话的Token消耗呈指数级增长(从几分钱的成本涨到几块钱甚至几十块钱),还会导致模型出现**“上下文稀释”(Context Dilution)**现象——模型会优先关注当前上下文中的最近输入,或者是和当前任务强相关但重复出现的信息,而你之前精心输入的那些“细节记忆点”,比如Lisa的全名、奶糕猫条的品牌、茉莉乌龙的温度,很快就会被模型“遗忘在角落的灰尘里”。
这种“短期记忆强、长期记忆弱”的问题,恰恰是目前绝大多数通用大语言模型(LLMs)和基于LLMs构建的单任务/简单多任务AI Agent的核心痛点之一。而解决这个痛点的关键,就在于为AI Agent构建一套结构化、可检索、可更新、可推理的长期记忆系统(Long-Term Memory System, LTM)——这正是AI Agent Harness Engineering(AI Agent 工程化封装与构建)领域中最热门、也最具挑战性的研究方向之一。
1.2 定义问题/阐述背景 (The “Why”)
1.2.1 什么是AI Agent Harness Engineering?
在正式切入长期记忆系统的话题之前,我们需要先明确一下本文的基础语境:AI Agent Harness Engineering。
简单来说,AI Agent Harness Engineering 是指将通用大语言模型(LLMs)、计算机视觉(CV)、语音识别(ASR)、语音合成(TTS)等基础AI技术,与工具调用(Tool Calling)、感知(Perception)、行动(Action)、规划(Planning)、反思(Reflection)等Agent核心能力进行工程化封装、组合、优化的方法论和技术体系。它的目标是让AI Agent从“只能回答问题、生成文本的‘聊天机器人’”,转变为“能够理解环境、制定计划、调用工具、执行任务、反思优化的‘智能助手’甚至‘自主智能体’”。
目前,AI Agent Harness Engineering领域已经有了很多成熟的框架和工具,比如:
- LangChain:最流行的开源AI Agent框架,支持链式调用、工具调用、记忆管理、向量检索等核心功能;
- LlamaIndex (GPT Index):专注于“知识增强型AI Agent”的开源框架,支持多种数据源的索引构建、向量检索、图检索等;
- AutoGPT:早期的“自主AI Agent”开源项目,虽然现在热度有所下降,但它提出的“目标分解→计划制定→工具调用→结果反思→目标更新”的闭环逻辑,对后续的Agent框架产生了深远的影响;
- OpenAI Assistants API:OpenAI官方推出的AI Agent服务,内置了代码解释器、文件检索、函数调用等工具,还支持“持久化线程(Persistent Threads)”作为短期记忆的补充;
- CrewAI:专注于“多Agent协作(Multi-Agent Collaboration)”的开源框架,支持将不同职责的Agent组合成“团队”,共同完成复杂任务。
不过,无论是开源框架还是官方服务,目前它们提供的默认记忆管理方案都存在一定的局限性——这也是我们今天要重点讨论的问题。
1.2.2 现有AI Agent记忆管理方案的局限性
按照LangChain创始人Harrison Chase提出的**Agent记忆金字塔(Agent Memory Pyramid)**理论,AI Agent的记忆可以分为以下四个层次(从底层到顶层,记忆的容量越来越小,但访问速度和重要性越来越高):
- 感官记忆(Sensory Memory):对应人类的“瞬时记忆”,存储Agent刚刚感知到的原始数据(比如用户的语音输入、摄像头拍摄的图像、传感器采集的温度数据等),容量极大,但保留时间极短(通常只有几毫秒到几秒钟);
- 短期记忆(Short-Term Memory, STM):对应人类的“工作记忆”,存储Agent当前正在处理的任务相关信息(比如当前对话的上下文、正在执行的任务的中间结果、正在调用的工具的参数等),容量较小(通常对应LLMs的上下文窗口大小,比如GPT-4o Mini是128K Token,Claude 3 Opus是200K Token),保留时间较短(通常只有当前对话或当前任务执行期间);
- 长期记忆(Long-Term Memory, LTM):对应人类的“长时记忆”,存储Agent过去积累的所有知识、经验、对话历史、任务结果等,容量理论上无限大,保留时间理论上永久;
- 元记忆(Meta-Memory):对应人类的“元认知”,存储Agent对自身记忆系统的认知(比如哪些记忆是重要的、哪些记忆可以删除、如何快速检索到需要的记忆等),容量极小,但对Agent的性能和可靠性至关重要。
目前,大多数开源框架和官方服务提供的默认记忆管理方案,主要集中在短期记忆和**基于向量检索的长期记忆(Vector-Based LTM)**两个层次:
- 短期记忆的默认方案:通常是直接使用LLMs的上下文窗口,或者是使用简单的“滑动窗口(Sliding Window)”算法——即只保留当前对话中最近的N个Token或N轮对话,超过这个限制的内容会被直接丢弃;
- 基于向量检索的长期记忆的默认方案:通常是使用嵌入模型(Embedding Model,比如OpenAI的text-embedding-3-small、text-embedding-3-large,或者是Hugging Face的sentence-transformers系列模型)将历史对话、知识文档等非结构化文本转换成高维向量(High-Dimensional Vector),然后将这些向量存储在向量数据库(Vector Database,比如Pinecone、Chroma、Weaviate、Milvus等)中;当Agent需要检索记忆时,会将当前的查询文本也转换成高维向量,然后在向量数据库中进行相似度检索(Similarity Search),找到与当前查询最相关的前K条记忆,再将这些记忆拼接成上下文,输入到LLMs中。
虽然这两种方案在一定程度上解决了AI Agent的记忆问题,但它们都存在明显的局限性:
- 短期记忆的局限性:
- 容量有限:即使是Claude 3 Opus的200K Token上下文窗口,也只能存储大约150页的英文文本(或者75页左右的中文文本)——对于需要处理大量历史数据的复杂任务(比如法律文档审查、医疗病历分析、企业知识问答等)来说,这远远不够;
- 上下文稀释:如前面的钩子中提到的,当上下文窗口中塞满了大量信息时,模型会优先关注最近的输入或强相关的重复信息,而细节记忆点很容易被忽略;
- Token消耗高:每次对话都需要将整个上下文窗口(或滑动窗口)的内容输入到LLMs中,当上下文窗口很大时,Token消耗会非常高——这对于企业级应用来说,是一个不可忽视的成本问题;
- 基于向量检索的长期记忆的局限性:
- 无法处理结构化关系:向量检索本质上是一种**“语义相似度匹配”,它只能找到与当前查询“语义相近”的文本片段,但无法理解文本片段之间的结构化关系(Structured Relationships)——比如,在前面的钩子中,向量检索可以找到“毛球打翻了保温杯”、“Lisa给了毛球猫条”这两个语义相近的文本片段,但它无法明确地回答“毛球上周三在茶水间和谁互动了?”、“Lisa的保温杯是什么颜色的?”、“毛球舔的是什么?”这类需要“关系推理”(Relational Reasoning)**的问题;
- 检索精度低:向量检索的精度很大程度上取决于嵌入模型的质量、向量数据库的检索算法、以及记忆的预处理方式——如果嵌入模型没有很好地理解某个领域的专业术语,或者记忆的预处理方式不当(比如没有将长文档切分成合适的段落),那么检索结果很可能会包含大量不相关的信息,或者遗漏掉真正重要的信息;
- 可解释性差:向量检索是一种“黑盒”操作——你很难解释为什么向量数据库会返回某条记忆,也很难解释模型为什么会基于这条记忆生成某个回答;
- 无法支持复杂的查询逻辑:向量检索通常只支持简单的“相似度Top-K查询”,无法支持复杂的**“图查询”(Graph Query)**——比如,“找出毛球过去一个月内互动过的所有人,以及这些人互动过的其他猫,再找出这些猫吃的所有品牌的猫条”——这类查询逻辑用向量数据库很难实现,甚至根本无法实现。
1.2.3 图数据库 Neo4j 在长期记忆构建中的优势
既然基于向量检索的长期记忆方案存在这么多局限性,那有没有一种更好的方案呢?答案是肯定的——那就是结合图数据库(Graph Database)和关系抽取(Relation Extraction, RE)技术的结构化长期记忆系统。
而在众多的图数据库中,Neo4j无疑是最成熟、最流行、功能最强大的一个——它是一个原生图数据库(Native Graph Database),采用了**属性图模型(Property Graph Model)**来存储数据,具有以下几个突出的优势:
- 原生图存储与处理:Neo4j采用了**“顶点优先存储(Vertex-Centric Storage)”和“免索引邻接(Index-Free Adjacency)”技术——这意味着,在Neo4j中,遍历图中的一条边(比如从“毛球”节点遍历到“Lisa Wang”节点)的时间复杂度是O(1),而在关系型数据库(RDBMS,比如MySQL、PostgreSQL)中,遍历同样的一条边通常需要执行多次JOIN操作,时间复杂度是O(n)甚至更高——这使得Neo4j在处理图遍历(Graph Traversal)和关系推理**任务时,性能远远超过关系型数据库和非原生图数据库;
- 直观的属性图模型:Neo4j的属性图模型由三个核心元素组成:
- 节点(Nodes):代表实体(Entities),比如人、猫、物品、地点、事件等;每个节点可以有一个或多个标签(Labels)(比如“Person”、“Cat”、“Item”、“Location”、“Event”),用来标识节点的类型;每个节点还可以有多个属性(Properties)(比如“name”、“age”、“color”、“brand”、“time”),用来存储节点的具体信息;
- 边(Relationships):代表实体之间的关系(Relations),比如“毛球”和“Lisa Wang”之间的“INTERACTED_WITH”关系、“毛球”和“原味皇家奶糕猫条”之间的“ATE”关系、“Lisa Wang”和“行政部”之间的“WORKS_IN”关系;每条边必须有一个类型(Type)(比如“INTERACTED_WITH”、“ATE”、“WORKS_IN”),用来标识关系的类型;每条边也可以有多个属性(Properties)(比如“time”、“location”、“count”、“description”),用来存储关系的具体信息;
- 属性(Properties):如前所述,节点和边都可以有属性,属性的类型可以是字符串、整数、浮点数、布尔值、日期时间、数组等;
这种属性图模型非常直观,和人类大脑存储和处理知识的方式非常相似——我们可以很容易地将现实世界中的实体和关系映射到Neo4j的属性图模型中;
- 强大的图查询语言 Cypher:Neo4j提供了一种专门为图查询设计的声明式查询语言——Cypher。Cypher的语法非常简单直观,类似于ASCII艺术画——比如,要查询“毛球上周三在茶水间和谁互动了?”,我们只需要写一条这样的Cypher语句:
即使你从来没有接触过Cypher,你也能大概看懂这条语句的意思——它先匹配了一个标签为“Cat”、名字为“毛球”的节点,然后匹配了从这个节点出发的、类型为“INTERACTED_WITH”的边,以及边指向的标签为“Person”的节点;接着,它筛选出了时间在上周三、地点在公司茶水间的边;最后,它返回了这个人的名字、互动的时间和互动的描述。MATCH (c:Cat {name: '毛球'})-[r:INTERACTED_WITH]->(p:Person) WHERE r.time >= datetime('202X-XX-XXT00:00:00') AND r.time <= datetime('202X-XX-XXT23:59:59') AND r.location = '公司茶水间' RETURN p.name, r.time, r.description
除了简单的匹配和筛选之外,Cypher还支持复杂的图遍历(比如最短路径查询、社区发现查询、子图匹配查询等)、关系推理(比如传递闭包查询、模式匹配查询等)、数据更新(比如创建节点、创建边、更新节点属性、更新边属性、删除节点、删除边等)、数据导入导出等功能——可以说,Cypher是目前最强大、最易用的图查询语言之一; - 丰富的生态系统:Neo4j拥有一个非常丰富的生态系统,包括:
- 官方工具:比如Neo4j Desktop(桌面版管理工具)、Neo4j AuraDB(云托管服务)、Neo4j Bloom(可视化探索工具)、Neo4j Data Importer(数据导入工具)、Neo4j Graph Data Science (GDS)(图数据科学库,支持社区发现、节点分类、链接预测、路径分析等算法)、Neo4j Python Driver(Python驱动程序)、Neo4j Java Driver(Java驱动程序)等;
- 第三方集成:比如和LangChain、LlamaIndex、AutoGPT、CrewAI等AI Agent框架的集成,和Pinecone、Chroma、Weaviate等向量数据库的集成,和OpenAI、Claude、Gemini等LLMs的集成,和Spark、Flink等大数据处理框架的集成,和Tableau、Power BI等数据可视化工具的集成等;
- 社区支持:Neo4j拥有一个非常活跃的社区,包括官方文档、官方博客、官方论坛、GitHub开源项目、Stack Overflow问答等——如果你在使用Neo4j的过程中遇到了问题,很容易就能在社区中找到解决方案;
- 可扩展性和可靠性:Neo4j支持水平扩展(Horizontal Scaling)和垂直扩展(Vertical Scaling)——其中,水平扩展可以通过Neo4j AuraDB的云托管服务或Neo4j Enterprise Edition的因果集群(Causal Cluster)来实现,垂直扩展可以通过增加服务器的CPU、内存、存储等资源来实现;此外,Neo4j还支持ACID事务(Atomicity、Consistency、Isolation、Durability),确保数据的一致性和可靠性——这对于企业级应用来说,是非常重要的。
1.2.4 关系抽取技术在长期记忆构建中的作用
不过,光有图数据库Neo4j还不够——我们还需要一种技术,能够将历史对话、知识文档等非结构化文本(Unstructured Text)转换成Neo4j属性图模型中的结构化节点和边(Structured Nodes & Relationships)——这种技术就是关系抽取(Relation Extraction, RE)。
关系抽取是自然语言处理(Natural Language Processing, NLP)领域中的一个核心任务,它的目标是从非结构化文本中识别出实体(Entities)以及实体之间的关系(Relations)——比如,从“毛球上周三在公司茶水间打翻了行政部Lisa Wang的薄荷绿虎牌316L保温杯”这句话中,关系抽取技术可以识别出以下实体和关系:
- 实体:
- 毛球(类型:Cat)
- 上周三(类型:Time)
- 公司茶水间(类型:Location)
- 行政部(类型:Department)
- Lisa Wang(类型:Person)
- 薄荷绿虎牌316L保温杯(类型:Item,子类型:Thermos)
- 关系:
- 毛球 →[时间:上周三,地点:公司茶水间,描述:打翻]→ 薄荷绿虎牌316L保温杯
- Lisa Wang →[所属部门:行政部]→ 行政部
- 薄荷绿虎牌316L保温杯 →[所有者:Lisa Wang]→ Lisa Wang
- 薄荷绿虎牌316L保温杯 →[颜色:薄荷绿]→ 薄荷绿(类型:Color)
- 薄荷绿虎牌316L保温杯 →[品牌:虎牌]→ 虎牌(类型:Brand)
- 薄荷绿虎牌316L保温杯 →[材质:316L不锈钢]→ 316L不锈钢(类型:Material)
在过去,关系抽取技术主要依赖于规则-based方法(Rule-Based Methods)和统计机器学习方法(Statistical Machine Learning Methods)——规则-based方法需要人工编写大量的规则,不仅工作量大,而且很难覆盖所有的场景;统计机器学习方法需要人工标注大量的训练数据,不仅成本高,而且泛化能力有限。
但近年来,随着**大语言模型(LLMs)的兴起,关系抽取技术取得了突破性的进展——现在,我们可以直接使用LLMs(比如GPT-4o、Claude 3 Opus、Gemini 1.5 Pro等)来进行零样本(Zero-Shot)或少样本(Few-Shot)**关系抽取,不需要人工编写规则,也不需要人工标注大量的训练数据,而且泛化能力非常强——这使得结合LLMs、关系抽取技术和图数据库Neo4j的结构化长期记忆系统,终于从“理论上的可能”变成了“工程上的可行”。
1.3 亮明观点/文章目标 (The “What” & “How”)
说了这么多,可能有些读者已经迫不及待地想知道:这篇文章到底要讲什么?读完这篇文章我能学到什么?
别着急,接下来我就来亮明本文的观点和目标:
1.3.1 本文的核心观点
本文的核心观点是:结合大语言模型(LLMs)的关系抽取能力和图数据库Neo4j的结构化存储、检索、推理能力,构建一套结构化、可检索、可更新、可推理的长期记忆系统,是解决目前AI Agent“短期记忆强、长期记忆弱”核心痛点的最佳方案之一——它不仅能够显著提高AI Agent的记忆容量和记忆精度,还能够支持复杂的关系推理和图查询,为AI Agent的“自主智能”提供坚实的基础。
1.3.2 本文的目标
本文的目标是通过一个完整的实战案例,带你从零开始,学习如何构建这套结构化长期记忆系统——具体来说,读完这篇文章你将学到:
- 基础知识:
- 什么是AI Agent的长期记忆系统?
- 什么是图数据库Neo4j?什么是属性图模型?什么是Cypher查询语言?
- 什么是关系抽取技术?如何使用LLMs进行零样本/少样本关系抽取?
- 如何将LLMs、关系抽取技术和图数据库Neo4j结合起来?
- 实战演练:
- 环境搭建:如何安装和配置Neo4j Desktop/Neo4j AuraDB?如何安装和配置Python环境?如何安装和配置所需的Python库(比如neo4j、langchain、openai、sentence-transformers等)?
- 系统设计:如何设计结构化长期记忆系统的架构?如何设计实体类型、关系类型和属性 schema?
- 核心实现:
- 如何使用LangChain和OpenAI的LLMs进行零样本/少样本实体识别(Named Entity Recognition, NER)和关系抽取?
- 如何将抽取到的实体和关系转换成Cypher语句?
- 如何使用Python Driver将Cypher语句执行到Neo4j数据库中?
- 如何使用Cypher语句从Neo4j数据库中检索需要的记忆?
- 如何将检索到的记忆拼接成上下文,输入到LLMs中,生成最终的回答?
- 如何实现记忆的更新和删除?
- 如何结合向量检索和图检索,实现“混合检索(Hybrid Retrieval)”,进一步提高记忆检索的精度?
- 进阶探讨:
- 常见陷阱与避坑指南:在构建这套系统的过程中,新手容易犯哪些错误?如何避免这些错误?
- 性能优化:如何优化Neo4j数据库的性能?如何优化关系抽取的速度?如何优化记忆检索的精度和速度?
- 成本考量:如何降低LLMs的Token消耗?如何降低Neo4j数据库的使用成本?
- 最佳实践总结:构建这套系统的最佳实践有哪些?
- 实际场景应用:这套结构化长期记忆系统可以应用在哪些实际场景中?比如法律文档审查、医疗病历分析、企业知识问答、智能客服、游戏NPC等。
- 行业发展与未来趋势:AI Agent的长期记忆系统领域的发展历史是怎样的?未来的发展趋势是什么?
1.3.3 本文的实战案例
为了让本文的内容更加具体、更加通俗易懂,我将选择一个**“智能宠物管家AI Agent”**作为实战案例——这个AI Agent的主要功能是:
- 记录宠物的生活数据:比如宠物的名字、品种、年龄、体重、饮食、运动、健康状况、互动记录等;
- 回答关于宠物的问题:比如“毛球上周吃了什么品牌的猫条?”、“毛球最近一次去宠物医院是什么时候?因为什么?”、“毛球和谁互动最多?”等;
- 提供个性化的建议:比如“毛球最近体重增长过快,建议减少皇家奶糕猫条的摄入量,增加逗猫棒的玩耍时间”等;
- 生成宠物的生活报告:比如“毛球202X年X月的生活报告”等。
在这个实战案例中,我们将使用:
- OpenAI GPT-4o Mini:作为核心的LLM,用于进行实体识别、关系抽取、回答问题、提供建议、生成报告等;
- OpenAI text-embedding-3-small:作为嵌入模型,用于将非结构化文本转换成高维向量,实现混合检索;
- Neo4j AuraDB Free Tier:作为图数据库,用于存储结构化的长期记忆;
- LangChain:作为AI Agent框架,用于串联LLMs、嵌入模型、向量数据库、图数据库等组件;
- Python 3.10+:作为开发语言。
二、基础知识/背景铺垫 (Foundational Concepts)
2.1 图数据库 Neo4j 核心概念
在正式开始实战演练之前,我们需要先深入了解一下图数据库Neo4j的核心概念——包括属性图模型、节点、边、属性、标签、类型、Cypher查询语言、Neo4j的架构等。
2.1.1 属性图模型(Property Graph Model)
如前面引言中提到的,Neo4j采用的是属性图模型(Property Graph Model)——这是目前最流行、最直观的图数据模型之一,由国际标准化组织(ISO)在2019年正式发布为ISO/IEC 39075标准。
属性图模型的核心思想非常简单:“现实世界中的一切事物都可以用节点来表示,事物之间的联系都可以用边来表示,事物和联系的具体信息都可以用属性来表示”——这句话听起来有点抽象,我们可以用前面钩子中的例子来具体说明一下:
2.1.1.1 钩子例子的属性图模型映射
前面钩子中的例子是:“毛球上周三在公司茶水间打翻了行政部Lisa Wang的薄荷绿虎牌316L保温杯,舔了一口洒在Lisa刚打印好的季度预算表上的茶渍,Lisa无奈之下给了毛球一条昨天剩下的原味皇家奶糕猫条”。
我们可以将这个例子中的实体和关系映射到Neo4j的属性图模型中,得到如图2-1所示的属性图(注意:为了简化起见,图中只展示了部分节点、边和属性):
图2-1:钩子例子的属性图模型映射(简化版)
从图2-1中,我们可以清楚地看到属性图模型的三个核心元素:
- 节点(Nodes):用圆角矩形表示(在Neo4j Desktop或Neo4j Bloom中,节点通常用圆形或椭圆形表示),每个节点都有一个或多个标签(比如“毛球”节点的标签是“Cat”,“薄荷绿虎牌316L保温杯”节点的标签是“Item”和“Thermos”),每个节点都有多个属性(比如“毛球”节点的属性有“name”、“breed”、“age”、“gender”);
- 边(Relationships):用带箭头的直线表示(注意:边是有方向的!——这是属性图模型和很多其他图数据模型(比如RDF图模型)的重要区别之一),每条边都有一个类型(比如“毛球”和“薄荷绿虎牌316L保温杯”之间的边的类型是“INTERACTED_WITH”),每条边也可以有多个属性(比如“时间”、“地点”、“描述”、“数量”);
- 属性(Properties):用键值对表示,节点和边都可以有属性,属性的类型可以是字符串、整数、浮点数、布尔值、日期时间、数组、点(Point)、线段(Line)、多边形(Polygon)等空间类型(Neo4j Enterprise Edition支持空间类型)。
接下来,我们将分别详细介绍这三个核心元素,以及标签、类型等相关概念。
2.1.1.2 节点(Nodes)
节点(Nodes)是属性图模型中的基本构建块之一,它代表现实世界中的实体(Entities)——比如人、猫、狗、物品、地点、时间、事件、组织、概念等。
在Neo4j中,每个节点都有以下几个特性:
- 唯一标识符(Node ID):每个节点在创建时都会被自动分配一个全局唯一的64位整数标识符(Node ID)——这个标识符是不可修改的,也不能被重复使用(即使节点被删除了,它的Node ID也不会被分配给新的节点);不过,需要注意的是,Node ID是Neo4j内部使用的标识符,我们在编写应用程序时,不应该依赖Node ID来标识节点——因为在Neo4j的因果集群中,不同的副本可能会给同一个节点分配不同的Node ID;相反,我们应该在节点上创建一个自定义的唯一属性(比如“name”、“id”、“uuid”),并在这个属性上创建一个唯一索引(Unique Index)或约束(Constraint),来确保节点的唯一性;
- 标签(Labels):每个节点可以有零个、一个或多个标签(Labels)——标签是用来**标识节点类型(Node Type)**的“标记”,它类似于关系型数据库中的“表名”,但比表名更加灵活(因为一个节点可以有多个标签,而关系型数据库中的一条记录只能属于一个表);
- 标签的命名规则:标签的名称必须以字母(A-Z、a-z)开头,后面可以跟字母、数字(0-9)或下划线(_);标签的名称是大小写敏感的(比如“Cat”和“cat”是两个不同的标签);
- 标签的作用:
- 分类节点:将不同类型的节点区分开来;
- 优化查询性能:当我们在Cypher语句中指定了标签时,Neo4j会只扫描具有该标签的节点,而不会扫描整个数据库中的所有节点——这可以显著提高查询性能;
- 创建索引和约束:我们只能在具有特定标签的节点的属性上创建索引和约束;
- 例如:在图2-1中,“毛球”节点的标签是“Cat”,“薄荷绿虎牌316L保温杯”节点的标签是“Item”和“Thermos”——这意味着,这个节点既是一个“物品”,也是一个“保温杯”;
- 属性(Properties):每个节点可以有零个或多个属性(Properties)——属性是用来**存储节点的具体信息(Node Data)**的“键值对”,它类似于关系型数据库中的“列”;
- 属性的命名规则:属性的名称必须以字母(A-Z、a-z)开头,后面可以跟字母、数字(0-9)或下划线(_);属性的名称是大小写敏感的(比如“name”和“Name”是两个不同的属性);
- 属性的类型:Neo4j支持以下几种属性类型(在Cypher中,我们可以使用
typeof()函数来查看属性的类型):属性类型 描述 示例 String 字符串 '毛球'、"Lisa Wang"Integer 64位有符号整数 2、500、-100Float 64位双精度浮点数 39.5、12.5、0.001Boolean 布尔值 true、falseDate 日期(不带时间) date('202X-10-23')Time 时间(不带日期,带时区或不带时区) time('14:30:00+08:00')、time('14:30:00')DateTime 日期时间(带时区或不带时区) datetime('202X-10-23T14:30:00+08:00')、datetime('202X-10-23T14:30:00')LocalDateTime 本地日期时间(不带时区) localdatetime('202X-10-23T14:30:00')LocalTime 本地时间(不带日期和时区) localtime('14:30:00')Duration 时间间隔 duration('P2Y3M4DT5H6M7S')(表示2年3个月4天5小时6分钟7秒)Point 空间点(2D或3D,地理坐标系或笛卡尔坐标系) point({latitude: 39.9042, longitude: 116.4074})(表示北京天安门的地理坐标)、point({x: 1.0, y: 2.0, z: 3.0})(表示笛卡尔坐标系中的一个3D点)Array 数组(数组中的元素必须是相同的类型) ['原味', '鸡肉味', '牛肉味']、[1, 2, 3, 4, 5]、[true, false, true] - 注意:Neo4j的属性类型是动态的——也就是说,同一个标签的不同节点可以有不同的属性,同一个属性在不同的节点上也可以有不同的类型(不过,我们不建议这样做,因为这会导致数据的不一致性,并且会降低查询性能);
- 例如:在图2-1中,“毛球”节点的属性有
name: '毛球'、breed: '橘猫'、age: 2、gender: '公';“薄荷绿虎牌316L保温杯”节点的属性有name: '薄荷绿虎牌316L保温杯'、capacity: 500。
2.1.1.3 边(Relationships)
边(Relationships)是属性图模型中的另一个基本构建块,它代表现实世界中实体之间的联系(Relations)——比如“毛球”和“Lisa Wang”之间的“INTERACTED_WITH”关系、“Lisa Wang”和“行政部”之间的“WORKS_IN”关系、“毛球”和“原味皇家奶糕猫条”之间的“ATE”关系等。
在Neo4j中,边有以下几个特性(注意:边的很多特性和节点是相似的,但也有一些重要的区别):
- 唯一标识符(Relationship ID):和节点一样,每条边在创建时都会被自动分配一个全局唯一的64位整数标识符(Relationship ID)——这个标识符也是不可修改的,也不能被重复使用;同样,我们在编写应用程序时,不应该依赖Relationship ID来标识边;
- 源节点(Source Node)和目标节点(Target Node):边是有方向的(Directed)——每条边都必须有一个源节点(Start Node / Source Node)和一个目标节点(End Node / Target Node);边的方向是非常重要的,因为它代表了实体之间关系的“语义”——比如,“毛球 →[ATE]→ 原味皇家奶糕猫条”和“原味皇家奶糕猫条 →[ATE]→ 毛球”的语义是完全不同的;
- 注意:虽然边是有方向的,但在Cypher语句中,我们可以忽略边的方向(只写
--而不写-->或<--),也可以指定边的方向是任意的(写<-->);
- 注意:虽然边是有方向的,但在Cypher语句中,我们可以忽略边的方向(只写
- 类型(Type):和节点的标签不同,每条边必须有且只有一个类型(Type)——边的类型是用来**标识关系类型(Relationship Type)**的“标记”,它类似于节点的标签,但比节点的标签更加严格(因为一条边只能有一个类型);
- 边的类型的命名规则:和节点的标签的命名规则完全相同——必须以字母开头,后面可以跟字母、数字或下划线;大小写敏感;
- 边的类型的作用:
- 分类边:将不同类型的边区分开来;
- 优化查询性能:当我们在Cypher语句中指定了边的类型时,Neo4j会只扫描具有该类型的边,而不会扫描整个数据库中的所有边——这可以显著提高查询性能;
- 例如:在图2-1中,“毛球”和“薄荷绿虎牌316L保温杯”之间的边的类型是“INTERACTED_WITH”;“Lisa Wang”和“行政部”之间的边的类型是“WORKS_IN”;
- 属性(Properties):和节点一样,每条边可以有零个或多个属性(Properties)——属性是用来**存储边的具体信息(Relationship Data)**的“键值对”;
- 边的属性的命名规则、类型、注意事项等,和节点的属性完全相同;
- 例如:在图2-1中,“毛球”和“薄荷绿虎牌316L保温杯”之间的边的属性有
time: '202X-10-23T14:30:00+08:00'、location: '公司茶水间'、description: '打翻并舔了一口茶渍';“毛球”和“原味皇家奶糕猫条”之间的边的属性有time: '202X-10-23T14:32:00+08:00'、location: '公司茶水间'、count: 1。
2.1.1.4 路径(Paths)
路径(Paths)是属性图模型中的一个派生概念——它是由一个或多个节点和零个或多个边组成的有序序列,其中,除了第一个节点之外,每个节点都必须是前一条边的目标节点;除了最后一个节点之外,每个节点都必须是后一条边的源节点。
路径的长度(Path Length)是指路径中包含的边的数量——比如:
- 只包含一个节点的路径的长度是0;
- 包含一个节点和一条边的路径的长度是1;
- 包含两个节点和一条边的路径的长度是
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)