导航菜单

  • 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 为什么需要语句组合?
  • 2. UNION操作
    • 2.1 前置知识:UNION操作
    • 2.2 UNION的基本语法
    • 2.3 UNION vs UNION ALL
    • 2.4 重要提示
    • 2.5 基本UNION操作
    • 2.6 UNION vs UNION ALL
  • 3. WITH子句
    • 3.1 前置知识:数据流管道
    • 3.2 WITH子句的作用
    • 3.3 WITH vs RETURN
    • 3.4 过滤聚合结果
    • 3.5 分组和收集
    • 3.6 链式处理
    • 3.7 设置查询参数
  • 4. 小结
    • 4.1 核心概念
    • 4.2 最佳实践
    • 4.3 常见用法

1. 什么是语句组合 #

在实际应用中,我们经常需要将多个查询的结果组合在一起,或者在查询过程中进行中间处理。Cypher提供了两种主要的方式来处理这些需求:

  1. UNION操作:将多个查询的结果合并在一起
  2. WITH子句:在查询过程中传递数据,进行中间处理

1.1 为什么需要语句组合? #

想象一下,如果你需要:

  • 查找所有演员和导演(需要合并两种不同的查询结果)
  • 先统计每个人的电影数量,然后只显示参演超过2部电影的人(需要中间处理)
  • 查找每个人的朋友,然后查找这些朋友喜欢的技术(需要链式处理)

这些场景都需要使用语句组合功能。

2. UNION操作 #

UNION操作用于将两个或多个查询的结果合并在一起。它类似于SQL中的UNION操作。

2.1 前置知识:UNION操作 #

UNION操作就像把两个篮子的东西合并到一个篮子里:

  • 如果两个篮子里有相同的东西(重复),UNION会自动去除重复
  • UNION ALL会保留所有东西,包括重复的

2.2 UNION的基本语法 #

查询1
UNION [ALL]
查询2

2.3 UNION vs UNION ALL #

操作 说明 行为 使用场景
UNION 组合结果并去除重复 自动去除重复行 需要唯一结果时
UNION ALL 组合结果但保留重复 保留所有行,包括重复 需要保留所有结果时

2.4 重要提示 #

使用UNION时,必须满足以下条件:

  1. 所有查询的返回列数量必须相同
  2. 所有查询的返回列类型必须匹配
  3. 所有查询的返回列别名必须相同

2.5 基本UNION操作 #

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

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

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

// 查找所有演员和导演(UNION会自动去除重复的Person)
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN p.name AS name, 'Actor' AS role
UNION
MATCH (p:Person)-[:DIRECTED]->(m:Movie)
RETURN p.name AS name, 'Director' AS role
ORDER BY name

// 查询最终结果
MATCH (p:Person)
RETURN p.name AS name
ORDER BY name

2.6 UNION vs UNION ALL #

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

// 创建测试数据
CREATE (p1:Person {name: "张三", city: "北京"}),
       (p2:Person {name: "李四", city: "上海"}),
       (p3:Person {name: "王五", city: "北京"})

// 查询插入后的数据
MATCH (p:Person)
RETURN p.name, p.city

// 使用 UNION(自动去重)
MATCH (p:Person {city: "北京"})
RETURN p.city AS city
UNION
MATCH (p:Person {city: "北京"})
RETURN p.city AS city

// 使用 UNION ALL(保留重复)
MATCH (p:Person {city: "北京"})
RETURN p.city AS city
UNION ALL
MATCH (p:Person {city: "北京"})
RETURN p.city AS city

3. WITH子句 #

WITH子句是Cypher中非常重要的功能,它允许你在查询过程中传递数据,进行中间处理。

3.1 前置知识:数据流管道 #

WITH子句就像工厂的流水线:

  • 第一步处理完的数据,通过WITH传递给第二步
  • 第二步可以对这些数据进行进一步处理
  • 可以有多条流水线(多个WITH子句)

3.2 WITH子句的作用 #

WITH子句用于:

  • 组合各个查询部分:将多个查询步骤连接起来
  • 声明数据流:指定哪些数据从一个部分流向另一个部分
  • 执行中间计算:在查询过程中进行计算和过滤
  • 类似于RETURN:但不结束查询,而是继续传递数据

3.3 WITH vs RETURN #

特性 WITH RETURN
作用 传递数据到下一部分 返回最终结果
查询继续 查询继续 ❌ 查询结束
使用场景 中间处理、过滤 最终输出
可以多次使用 可以链式使用 ❌ 通常只使用一次

3.4 过滤聚合结果 #

WITH最常见的用途是在聚合后进行过滤。

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

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

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

// 使用 WITH 在聚合后进行过滤
// 先统计每个人参演的电影数量
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WITH p, count(m) AS movieCount
// 然后过滤出参演超过1部电影的人
WHERE movieCount > 1
RETURN p.name, movieCount

// 查询最终结果
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WITH p, count(m) AS movieCount
WHERE movieCount > 1
RETURN p.name, movieCount
ORDER BY movieCount DESC

3.5 分组和收集 #

WITH可以用于按某个字段分组,并收集相关数据。

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

// 创建测试数据
CREATE (p1:Person {name: "张三", city: "北京"}),
       (p2:Person {name: "李四", city: "北京"}),
       (p3:Person {name: "王五", city: "上海"}),
       (p4:Person {name: "赵六", city: "上海"}),
       (m1:Movie {title: "长津湖"}),
       (m2:Movie {title: "满江红"}),
       (p1)-[:ACTED_IN]->(m1),
       (p2)-[:ACTED_IN]->(m1),
       (p3)-[:ACTED_IN]->(m2),
       (p4)-[:ACTED_IN]->(m2)

// 查询插入后的数据
MATCH (p:Person)
RETURN p.name, p.city

// 使用 WITH 按城市分组,并收集每个城市的人名
MATCH (p:Person)
WITH p.city AS city, collect(p.name) AS people
RETURN city, people, size(people) AS count

// 查询最终结果
MATCH (p:Person)
WITH p.city AS city, collect(p.name) AS people
RETURN city, people
ORDER BY city

3.6 链式处理 #

可以使用多个WITH子句进行链式处理,逐步处理数据。

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

// 创建测试数据
CREATE (p1:Person {name: "张三"}),
       (p2:Person {name: "李四"}),
       (p3:Person {name: "王五"}),
       (c1:Company {name: "科技公司"}),
       (t1:Technology {name: "Python"}),
       (t2:Technology {name: "Java"}),
       (p1)-[:WORKS_FOR]->(c1),
       (p2)-[:WORKS_FOR]->(c1),
       (p1)-[:LIKES]->(t1),
       (p1)-[:LIKES]->(t2),
       (p2)-[:LIKES]->(t1)

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

// 使用多个 WITH 子句进行链式处理
// 第一步:查找有工作关系的人
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
WITH p, c
// 第二步:查找这些人喜欢的技术
MATCH (p)-[:LIKES]->(t:Technology)
WITH p, c, collect(t.name) AS technologies
// 第三步:返回结果
RETURN p.name AS person, c.name AS company, technologies

// 查询最终结果
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
WITH p, c
MATCH (p)-[:LIKES]->(t:Technology)
WITH p, c, collect(t.name) AS technologies
RETURN p.name, c.name, technologies

3.7 设置查询参数 #

WITH可以用于在查询开始时设置参数,使查询更灵活和可读。

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

// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30, yearsExperience: 5}),
       (p2:Person {name: "李四", age: 25, yearsExperience: 3}),
       (p3:Person {name: "王五", age: 35, yearsExperience: 8}),
       (p4:Person {name: "赵六", age: 28, yearsExperience: 6})

// 查询插入后的数据
MATCH (p:Person)
RETURN p.name, p.age, p.yearsExperience

// 使用 WITH 设置查询参数
WITH 3 AS minExperience, 7 AS maxExperience
MATCH (p:Person)
WHERE minExperience <= p.yearsExperience <= maxExperience
RETURN p.name, p.yearsExperience

// 查询最终结果
WITH 3 AS minExperience, 7 AS maxExperience
MATCH (p:Person)
WHERE minExperience <= p.yearsExperience <= maxExperience
RETURN p.name, p.yearsExperience
ORDER BY p.yearsExperience

4. 小结 #

4.1 核心概念 #

概念 说明 主要用途
UNION 合并查询结果并去重 组合多个查询的结果
UNION ALL 合并查询结果但保留重复 保留所有结果,包括重复
WITH 传递数据到下一部分 中间处理、过滤聚合结果

4.2 最佳实践 #

  1. 使用UNION合并结果:当需要组合多个查询的结果时
  2. 使用WITH进行中间处理:当需要在聚合后进行过滤时
  3. 使用链式WITH:当需要多步处理数据时
  4. 使用WITH设置参数:使查询更灵活和可读

4.3 常见用法 #

  • 使用UNION合并不同查询的结果
  • 使用WITH在聚合后进行过滤
  • 使用WITH进行分组和收集
  • 使用链式WITH进行多步处理
  • 使用WITH设置查询参数
← 上一节 39.结果处理和聚合 下一节 41.子查询 →

访问验证

请输入访问令牌

Token不正确,请重新输入