导航菜单

  • 1.langchain.intro
  • 2.langchain.chat_models
  • 3.langchain.prompts
  • 4.langchain.example_selectors
  • 5.output_parsers
  • 6.Runnable
  • 7.memory
  • 8.document_loaders
  • 9.text_splitters
  • 10.embeddings
  • 11.tool
  • 12.retrievers
  • 13.optimize
  • 14.项目介绍
  • 15.启动HTTP
  • 16.数据与模型
  • 17.权限管理
  • 18.知识库管理
  • 19.设置
  • 20.文档管理
  • 21.聊天
  • 22.API文档
  • 23.RAG优化
  • 24.索引时优化
  • 25.检索前优化
  • 26.检索后优化
  • 27.系统优化
  • 28.GraphRAG
  • 29.图
  • 30.为什么选择图数据库
  • 31.什么是 Neo4j
  • 32.安装和连接 Neo4j
  • 33.Neo4j核心概念
  • 34.Cypher基础
  • 35.模式匹配
  • 36.数据CRUD操作
  • 37.GraphRAG
  • 38.查询和过滤
  • 39.结果处理和聚合
  • 40.语句组合
  • 41.子查询
  • 42.模式和约束
  • 43.日期时间处理
  • 44.Cypher内置函数
  • 45.Python操作Neo4j
  • 46.neo4j
  • 47.py2neo
  • 48.Streamlit
  • 49.Pandas
  • 50.graphRAG
  • 51.deepdoc
  • 52.deepdoc
  • 53.deepdoc
  • 55.deepdoc
  • 54.deepdoc
  • Pillow
  • 1. 什么是子查询
    • 1.1 前置知识:子查询的概念
    • 1.2 为什么需要子查询?
    • 1.3 Neo4j中的子查询类型
    • 1.4 关于子查询的重要事项
  • 2. EXISTS子查询
    • 2.1 前置知识:EXISTS的作用
    • 2.2 EXISTS子查询的基本语法
    • 2.3 基本EXISTS用法
    • 2.4 复杂EXISTS用法
  • 3. COUNT子查询
    • 3.1 前置知识:COUNT的作用
    • 3.2 COUNT子查询的基本语法
    • 3.3 COUNT vs EXISTS
    • 3.4 基本COUNT用法
  • 4. CALL子查询
    • 4.1 前置知识:CALL的作用
    • 4.2 CALL子查询的基本语法
    • 4.3 基本CALL用法
  • 5. 小结
    • 5.1 核心概念
    • 5.2 最佳实践
    • 5.3 常见用法

1. 什么是子查询 #

子查询是嵌套在另一个查询内部的查询。它就像在一个大问题中问一个小问题,然后用小问题的答案来帮助回答大问题。

1.1 前置知识:子查询的概念 #

想象一下,如果你要查找"所有在Neo4j公司工作的人的朋友",你需要:

  1. 先找到在Neo4j公司工作的人(这是子查询)
  2. 然后找到这些人的朋友(这是主查询)

子查询就是用来完成第一步的。

1.2 为什么需要子查询? #

子查询可以帮助我们:

  • 简化复杂查询:将复杂问题分解为多个小问题
  • 提高代码可读性:使查询逻辑更清晰
  • 实现复杂过滤:在WHERE子句中进行复杂的条件检查
  • 组合多个查询结果:将不同查询的结果合并在一起

1.3 Neo4j中的子查询类型 #

Neo4j支持以下类型的子查询(从Neo4j 4.0开始):

子查询类型 描述 版本 主要用途
EXISTS 检查是否存在匹配模式 Neo4j 4.0+ 模式存在性检查
COUNT 计算匹配模式的数量 Neo4j 4.0+ 需要知道匹配数量
CALL {...} 执行结果返回子查询 Neo4j 4.0+ 组合多个查询结果

1.4 关于子查询的重要事项 #

使用子查询时,需要注意以下几点:

  1. 子查询由大括号{ }界定

    • 所有子查询都必须用大括号包围
  2. 变量作用域

    • 子查询可以访问外部查询的变量
    • 子查询中的变量不会影响外部查询(除非通过RETURN返回)
  3. 必须显式传递变量

    • 如果子查询需要使用外部查询的变量,必须显式传递
  4. 返回要求

    • EXISTS子查询只需要返回至少一行(返回true/false)
    • CALL子查询必须返回结果
    • COUNT子查询返回数字

2. EXISTS子查询 #

EXISTS子查询用于检查是否存在匹配的模式。它返回布尔值(true/false),就像问"有没有这样的数据?"

2.1 前置知识:EXISTS的作用 #

EXISTS就像问一个问题:"有没有符合条件的数据?"

  • 如果有:返回true
  • 如果没有:返回false

2.2 EXISTS子查询的基本语法 #

WHERE EXISTS {
  MATCH ...
  [WHERE ...]
  RETURN ...
}

2.3 基本EXISTS用法 #

最简单的EXISTS子查询用于检查某个模式是否存在。

// 清空数据库
MATCH (n) DETACH DELETE n

// 创建测试数据
CREATE (jennifer:Person {name: 'Jennifer'}),
       (mark:Person {name: 'Mark'}),
       (john:Person {name: 'John'}),
       (neo4j:Company {name: 'Neo4j'}),
       (xyz:Company {name: 'XYZ'}),
       (jennifer)-[:IS_FRIENDS_WITH]->(mark),
       (jennifer)-[:IS_FRIENDS_WITH]->(john),
       (jennifer)-[:WORKS_FOR]->(neo4j),
       (mark)-[:WORKS_FOR]->(xyz)

// 查询插入后的数据
MATCH (p:Person)-[r]->(target)
RETURN p.name, type(r), target

// 使用EXISTS子查询查找在Neo4j工作的人的朋友
// 第一步:MATCH匹配所有朋友关系
// 第二步:WHERE EXISTS检查这个人是否在Neo4j公司工作
// EXISTS子查询中的变量p来自外部查询
// 如果子查询返回至少一行,EXISTS返回true
MATCH (p:Person)-[r:IS_FRIENDS_WITH]->(friend:Person)
WHERE EXISTS {
  MATCH (p)-[:WORKS_FOR]->(:Company {name: 'Neo4j'})
}
RETURN p.name AS person, friend.name AS friend
ORDER BY p.name, friend.name

// 查询最终结果
MATCH (p:Person)-[r:IS_FRIENDS_WITH]->(friend:Person)
WHERE EXISTS {
  MATCH (p)-[:WORKS_FOR]->(:Company {name: 'Neo4j'})
}
RETURN p.name, friend.name
ORDER BY p.name, friend.name

2.4 复杂EXISTS用法 #

EXISTS子查询可以包含复杂的逻辑,包括多个MATCH和WHERE条件。

// 清空数据库
MATCH (n) DETACH DELETE n

// 创建测试数据
CREATE (diana:Person {name: 'Diana'}),
       (melissa:Person {name: 'Melissa'}),
       (graphs:Technology {type: 'Graphs'}),
       (java:Technology {type: 'Java'}),
       (query:Technology {type: 'Query Languages'}),
       (companyX:Company {name: 'Company X'}),
       (companyA:Company {name: 'Company A'}),
       (diana)-[:WORKS_FOR]->(companyX),
       (melissa)-[:WORKS_FOR]->(companyA),
       (diana)-[:LIKES]->(graphs),
       (melissa)-[:LIKES]->(graphs),
       (diana)-[:LIKES]->(query),
       (melissa)-[:LIKES]->(query),
       (john:Person {name: 'John'})-[:LIKES]->(java),
       (jennifer:Person {name: 'Jennifer'})-[:LIKES]->(graphs)

// 查询插入后的数据
MATCH (p:Person)-[r]->(target)
RETURN p.name AS Person, type(r) AS Relationship, target.name AS TargetName, target.type AS TargetType
ORDER BY Person

// 查找满足以下条件的人:
// 1. 在名称以"Company"开头的公司工作
// 2. 喜欢至少1种被3人或以上喜欢的技术
//
// 第一步:MATCH匹配在Company开头的公司工作的人
// 第二步:WHERE EXISTS检查是否存在被3人以上喜欢的技术
// 在EXISTS子查询中,使用COUNT子查询计算喜欢该技术的人数
MATCH (person:Person)-[:WORKS_FOR]->(company)
WHERE company.name STARTS WITH "Company"
AND EXISTS {
  MATCH (person)-[:LIKES]->(t:Technology)
  WHERE COUNT { (t)<-[:LIKES]-(:Person) } >= 3
}
RETURN person.name AS person, company.name AS company
ORDER BY person.name

// 查询最终结果
MATCH (person:Person)-[:WORKS_FOR]->(company)
WHERE company.name STARTS WITH "Company"
AND EXISTS {
  MATCH (person)-[:LIKES]->(t:Technology)
  WHERE COUNT { (t)<-[:LIKES]-(:Person) } >= 3
}
RETURN person.name, company.name
ORDER BY person.name

3. COUNT子查询 #

COUNT子查询用于计算匹配模式的数量。它在WHERE子句中使用,就像问"有多少个符合条件的数据?"

3.1 前置知识:COUNT的作用 #

COUNT就像数数:"有多少个符合条件的数据?"

  • 返回一个数字
  • 可以用于比较(如 > 1, >= 3等)

3.2 COUNT子查询的基本语法 #

WHERE COUNT { 模式 } 操作符 数值

3.3 COUNT vs EXISTS #

特性 COUNT EXISTS
返回值 数字 布尔值(true/false)
性能 需要计算所有匹配 找到第一个就返回
使用场景 需要知道具体数量 只需要知道是否存在
效率 较慢 较快

3.4 基本COUNT用法 #

// 清空数据库
MATCH (n) DETACH DELETE n

// 创建测试数据
CREATE (jennifer:Person {name: 'Jennifer'}),
       (mark:Person {name: 'Mark'}),
       (john:Person {name: 'John'}),
       (sally:Person {name: 'Sally'}),
       (ann:Person {name: 'Ann'}),
       (jennifer)-[:IS_FRIENDS_WITH]->(mark),
       (jennifer)-[:IS_FRIENDS_WITH]->(john),
       (jennifer)-[:IS_FRIENDS_WITH]->(sally),
       (jennifer)-[:IS_FRIENDS_WITH]->(ann),
       (john)-[:IS_FRIENDS_WITH]->(sally),
       (mark)-[:IS_FRIENDS_WITH]->(ann)

// 查询插入后的数据
MATCH (p:Person)-[r:IS_FRIENDS_WITH]->(friend:Person)
RETURN p.name, friend.name

// 使用COUNT子查询查找有3个或以上朋友的人
MATCH (p:Person)
WHERE COUNT { (p)-[:IS_FRIENDS_WITH]->(:Person) } >= 3
RETURN p.name, COUNT { (p)-[:IS_FRIENDS_WITH]->(:Person) } AS friend_count

// 查询最终结果
MATCH (p:Person)
WHERE COUNT { (p)-[:IS_FRIENDS_WITH]->(:Person) } >= 3
RETURN p.name, COUNT { (p)-[:IS_FRIENDS_WITH]->(:Person) } AS friend_count

4. CALL子查询 #

CALL子查询用于执行一个独立的查询,并将结果与主查询合并。它类似于SQL中的子查询。

4.1 前置知识:CALL的作用 #

CALL子查询就像执行一个独立的查询,然后将结果与主查询合并。

4.2 CALL子查询的基本语法 #

CALL {
  MATCH ...
  RETURN ...
}
RETURN ...

4.3 基本CALL用法 #

// 清空数据库
MATCH (n) DETACH DELETE n

// 创建测试数据
CREATE (p1:Person {name: '张三'}),
       (p2:Person {name: '李四'}),
       (m1:Movie {title: '长津湖'}),
       (m2:Movie {title: '满江红'}),
       (p1)-[:ACTED_IN]->(m1),
       (p2)-[:ACTED_IN]->(m2)

// 查询插入后的数据
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN p.name, m.title

// 使用CALL子查询查找所有演员和电影
CALL {
  MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
  RETURN p.name AS name, m.title AS title, 'Actor' AS role
}
RETURN name, title, role
ORDER BY name

// 查询最终结果
CALL {
  MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
  RETURN p.name AS name, m.title AS title, 'Actor' AS role
}
RETURN name, title, role
ORDER BY name

5. 小结 #

5.1 核心概念 #

概念 说明 主要用途
EXISTS子查询 检查是否存在匹配模式 模式存在性检查
COUNT子查询 计算匹配模式的数量 需要知道匹配数量
CALL子查询 执行独立的查询 组合多个查询结果

5.2 最佳实践 #

  1. 使用EXISTS检查存在性:当只需要知道是否存在时,使用EXISTS比COUNT更高效
  2. 使用COUNT计算数量:当需要知道具体数量时,使用COUNT
  3. 使用CALL组合查询:当需要组合多个独立查询的结果时,使用CALL

5.3 常见用法 #

  • 使用EXISTS检查模式是否存在
  • 使用COUNT计算匹配数量
  • 使用CALL组合多个查询结果
  • 在WHERE子句中使用子查询进行复杂过滤
← 上一节 40.语句组合 下一节 42.模式和约束 →

访问验证

请输入访问令牌

Token不正确,请重新输入