设置和查询复合数据库

本节中提供的示例使用了两个 Cypher 子句:USECALL {}

图数据库设置

要重现此页面上的示例,需要进行以下设置

创建一个标准数据库 movies2022
CREATE DATABASE movies2022
创建一个复合数据库 cineasts
CREATE COMPOSITE DATABASE cineasts
为复合数据库中的本地数据库创建数据库别名 cineasts.latest
CREATE ALIAS `cineasts`.`latest`
  FOR DATABASE movies2022
为复合数据库中的远程数据库创建数据库别名 cineasts.upcoming
CREATE ALIAS `cineasts`.`upcoming`
  FOR DATABASE upcoming
  AT 'neo4j+s://location:7687'
  USER neo4j
  PASSWORD 'password'

有关复合数据库和复合数据库中数据库别名的更多信息,请参阅概念管理复合数据库中的数据库别名

图选择

提交到复合数据库的查询可能包含多个 USE 子句,这些子句将查询的不同部分引导到不同的组成图。

每个组成图以将其引入复合数据库的别名命名。

查询单个图

示例 1. 读取和返回来自单个图的数据
USE cineasts.latest
MATCH (movie:Movie)
RETURN movie.title AS title

查询开头处的 USE 子句为所有后续子句选择 cineasts.latest 图。MATCH 在该图上执行。

查询多个图

示例 2. 读取和返回来自两个图的数据
USE cineasts.latest
MATCH (movie:Movie)
RETURN movie.title AS title
  UNION
USE cineasts.upcoming
MATCH (movie:Movie)
RETURN movie.title AS title

UNION 查询的第一部分选择 cineasts.latest 图,第二部分选择 cineasts.upcoming 图。

动态图访问

查询还可以使用 USE graph.byName(graphName) 形式动态选择组成图。

示例 3. 读取和返回来自动态选择图的数据
UNWIND ['cineasts.latest', 'cineasts.upcoming'] AS graphName
CALL {
  USE graph.byName(graphName)
  MATCH (movie:Movie)
  RETURN movie
}
RETURN movie.title AS title

在上面的示例中,访问图数据的查询部分 MATCH (movie:Movie) 包含在一个带有动态 USE 子句的子查询中。UNWIND 用于获取我们图的名称,每个名称在一行上。CALL {} 子查询对每个输入行执行一次。在本例中,一次选择 cineasts.latest,一次选择 cineasts.upcoming

列出图

内置函数 graph.names() 返回一个列表,其中包含当前复合数据库上所有组成图的名称。

示例 4. graph.names() 函数
UNWIND graph.names() AS graphName
RETURN graphName
+---------------------+
| graphName           |
+---------------------+
| "cineasts.latest"   |
| "cineasts.upcoming" |
+---------------------+

此函数返回的名称可用于动态图访问。

示例 5. 读取和返回来自所有图的数据
UNWIND graph.names() AS graphName
CALL {
  USE graph.byName(graphName)
  MATCH (movie:Movie)
  RETURN movie
}
RETURN movie.title

查询结果聚合

示例 6. 获取所有图中所有电影的最早上映年份
UNWIND graph.names() AS graphName
CALL {
  USE graph.byName(graphName)
  MATCH (movie:Movie)
  RETURN movie.released AS released
}
RETURN min(released) AS earliest

子查询返回每个组成图中每部电影的 released 属性。主查询末尾的 RETURN 在整个结果中聚合以计算全局最小值。

相关子查询

此查询查找 cineasts.upcoming 中所有将在 cineasts.latest 中最长电影的同一个月上映的电影。

示例 7. 相关子查询
CALL {
  USE cineasts.latest
  MATCH (movie:Movie)
  RETURN movie.releasedMonth AS monthOfLongest
    ORDER BY movie.runningTime DESC
    LIMIT 1
}
CALL {
  USE cineasts.upcoming
  WITH monthOfLongest
  MATCH (movie:Movie)
  WHERE movie.releasedMonth = monthOfLongest
  RETURN movie
}
RETURN movie

查询的第一部分从 cineasts.latest 中找到运行时间最长的电影,并返回其上映月份。查询的第二部分查找满足我们条件的 cineasts.upcoming 中的所有电影并返回它们。子查询使用 WITH monthOfLongest 导入 monthOfLongest 变量,使其可访问。

更新

复合数据库查询可以对组成图执行更新。

示例 8. 组成图更新
USE cineasts.upcoming
CREATE (:Movie {title: 'Dune: Part Two'})

每个事务只能对单个组成图执行更新。

示例 9. 多图更新将失败
UNWIND graph.names() AS graphName
CALL {
  USE graph.byName(graphName)
  CREATE (:Movie {title: 'The Flash'})
}
Writing to more than one database per transaction is not allowed.

限制

复合数据库上的查询有一些限制。

图访问操作

考虑一个复合数据库查询

UNWIND graph.names() AS graphName
CALL {
  USE graph.byName(graphName)
  MATCH (movie:Movie)
  RETURN movie
}
RETURN movie

这里的外层子句,即 UNWINDCALL 本身和最终的 RETURN,出现在查询的根作用域中,没有特定的选定图。在未指定图的作用域中的子句或表达式不得是图访问的。

以下复合数据库查询无效,因为 [p=(movie)-→() | p] AS paths 是查询根作用域中的图访问操作

UNWIND graph.names() AS graphName
CALL {
  USE graph.byName(graphName)
  MATCH (movie:Movie)
  RETURN movie
}
RETURN [p=(movie)-->() | p] AS paths

查看图访问操作的示例

  • RETURN 1 + 2 AS number

  • WITH node.property AS val

嵌套 USE 子句

内部作用域必须使用与其外部作用域相同的图

USE cineasts.latest
MATCH (n)
CALL {
  USE cineasts.upcoming
  MATCH (m)
  RETURN m
}
RETURN n, m
Nested subqueries must use the same graph as their parent query.
Attempted to access graph cineasts.upcoming
"    USE cineasts.upcoming"
     ^

没有 USE 子句的子查询可以嵌套。它们继承来自外部作用域的指定图。

CALL {
  USE cineasts.upcoming
  CALL {
    MATCH (m:Movie)
    RETURN m
  }
  RETURN m
}
RETURN m

Cypher 运行时

当查询提交到复合数据库时,查询的不同部分可能会使用不同的运行时运行。在未指定图的作用域中的子句或表达式使用插槽运行时运行。引导到不同组成图的查询部分使用该图的默认运行时运行,或者如果指定,则尊重提交的 Cypher 查询选项

内置图函数

图函数位于 graph 命名空间中。下表描述了这些函数

表 1. 内置图函数
函数 说明

graph.names()

提供当前复合数据库上所有组成图的名称列表。

graph.byName(graphName)

USE 子句一起使用,以动态地按名称选择组成图。此函数仅支持 USE 子句。

graph.propertiesByName(graphName)

返回一个包含与给定图关联的属性的映射。

有关更多信息,请参阅Cypher 手册中的图函数