基于 Cypher 的视图

简介

Cypher®-backed 视图是一种在 JDBC 客户端应用程序内部创建虚拟视图的方式,这些视图由任意 Cypher 查询支持。它们能够让您的 Neo4j 数据库以最佳方式被利用,并使用所有 Cypher 构造,包括 JDBC 驱动能够提供直接 SQL 到 Cypher 转换的所有内容。

基于 Cypher 的视图将出现在 JDBC 连接的数据库元数据中,并在客户端侧定义。它们由以下部分组成

  • 名称

  • Cypher 查询

  • 列列表

名称必须唯一,并且将作为可查询的视图名称出现在数据库元数据中。仅列出的列会出现在数据库元数据中。

要求

基于 Cypher 的视图需要启用 SQL 翻译,并在类路径上拥有 默认翻译器,因此必须在应用程序中添加相应的依赖或使用 完整捆绑包。如果未启用 SQL 翻译或缺少标准翻译器,Cypher‑backed 视图仍会被加载并出现在数据库元数据中,但无法对其进行查询。

虽然您可以在视图定义中使用任何有效的 Cypher 查询,但我们强烈建议不要使用对图进行更新的 Cypher 语句。我们并不解析 Cypher,也不会阻止类似 SELECT * 的语句在视图定义中随意使用 MATCH (n) DETACH DELETE 删除图。但我们会阻止基于 Cypher 的视图用于 SQL 更新语句,例如 INSERTDELETEUPDATE

Cypher 查询基本上可以是任意形状,但它必须是能够在 CALL {} 子查询中有效的查询。虽然我们可以直接执行该查询,但否则您将无法一次查询多个基于 Cypher 的视图。更多信息请查看下面的 “限制”。

配置和视图定义格式

基于 Cypher 的视图以 JSON 表示。原生格式由下面的 模式 定义

清单 1. 基于 Cypher 的视图的 JSON 模式
{
  "$schema": "https://schema.json.js.cn/draft-07/schema#",
  "title": "JSON Schema for Cypher-backed views",
  "type": "array",
  "items": {
    "$ref": "#/$defs/viewType"
  },
  "$defs": {
    "viewType": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of this view."
        },
        "query": {
          "type": "string",
          "description": "Any valid Cypher query."
        },
        "columns": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/columnType"
          }
        }
      },
      "required": [
        "name",
        "query",
        "columns"
      ],
      "title": "A view that will be queryable."
    },
    "columnType": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name as it will appear in the column list of the view."
        },
        "propertyName": {
          "type": "string",
          "description": "The property to pick from the graph, can be omitted when equal to the column name"
        },
        "type": {
          "type": "string",
          "description": "The Neo4j type of this column"
        }
      },
      "required": [
        "name",
        "type"
      ],
      "description": "A type representing a column in a relational view"
    }
  }
}

JDBC 驱动能够从以下位置加载资源

  • 文件系统

  • 或通过 http(s)

并且这些资源必须通过名为 viewDefinitions 的连接属性进行配置。该属性可以作为查询参数放入 JDBC URL,亦可作为 JDBC 属性。以下是一系列在 JDBC URL 中使用查询参数的示例

请注意我们对 文件 URI 方案 的斜杠数量非常严格:file: 是协议,斜杠不属于协议本身。要么使用恰好一个斜杠(/)表示没有主机名,要么使用三个斜杠(///)表示空主机名(效果相同)。我们不会对两个斜杠的含义作猜测,也不支持使用主机名读取文件。
jdbc:neo4j://:7687?viewDefinitions=file:/my/views/foobar.json

这里的视图定义位于同一机器的文件夹 /my/views/,文件名为 foobar.json

jdbc:neo4j://:7687?viewDefinitions=file:///my/views/foobar.json

这等同于上面的 URL

jdbc:neo4j://:7687?viewDefinitions=https://myorg.com/movies.json

在安全网页服务器上托管的视图定义

请确保仅从受信任的来源加载视图定义。如上所述,没有任何机制阻止将编写的 Cypher 查询用作视图定义,而您不希望它们被未知或不受信任的来源注入到您的应用程序中。

一个简单的示例如下

清单 2. 一个返回所有电影及其演员的基于 Cypher 的视图。
[
  {
    "name": "v_movie_actors",
    "query": "MATCH (n:Movie)<-[:ACTED_IN]-(p:Person) RETURN elementId(n) AS id, n.title AS title, n.released AS released, collect(p.name) AS actors",
    "columns": [
      {
        "name": "id",
        "type": "STRING"
      },
      {
        "name": "title",
        "type": "STRING"
      },
      {
        "name": "released",
        "type": "INTEGER"
      },
      {
        "name": "actors",
        "type": "LIST"
      }
    ]
  }
]

在上述示例中,所有列都在 Cypher 的 RETURN 子句中投影,并使用 AS 将其命名为列列表中对应的列名。可以按如下方式查询该视图,排序和谓词会下推到实际查询中。

清单 3. 查询 v_movie_actors
SELECT * FROM v_movie_actors ORDER BY title

columnType 对象的 propertyName 属性可用于引用 Cypher 实体(节点或关系)的属性,如下面的示例所示

清单 4. 定义一个使用虚拟列(id 函数)和 Cypher 查询返回实体的视图
[
  {
    "name": "people",
    "query": "MATCH (n:Person) RETURN id(n) AS id, n",
    "columns": [
      {
        "name": "id",
        "type": "INTEGER"
      },
      {
        "name": "name",
        "propertyName": "n.name",
        "type": "STRING"
      }
    ]
  }
]

现在可以这样查询

清单 5. 查询 v_people
SELECT * FROM v_people WHERE name LIKE 'A%' ORDER BY name

正如在 v_movie_actors 示例中的 ORDER BY 子句一样,谓词和排序子句将下推到传递给 Neo4j DBMS 的实际 Cypher 中。

另外,我们支持与 “Magnitude Simba Neo4j 数据连接器(用于商业智能工具)” 1.0.10 版(截至 2022 年 1 月)相同的格式。不过所有的模式信息将被忽略(模式名称以及视图是否隐藏)。

限制

基于 Cypher 的视图当然只能读取,不能修改(既不能更新也不能删除)。基于 Cypher 的视图不能与常规“表”混用,即那些被视为标签并随后进行匹配的表。如果想一次查询多个基于 Cypher 的视图,需要在 FROM 子句中枚举它们,例如 view1, view2, view3,并在 WHERE 子句中使用类似 view1.x = view2.y 的谓词进行适当的连接。不能使用 JOINLEFT OUTER 或任何其他 JOIN 子句,因为我们无法从基于 Cypher 的视图中推导出任何有意义的关系,这在此类情况下是我们尝试的内容。

这些限制其实影响不大,因为您可以在构成视图的查询中表达任意复杂的表达式,从而使您的 ETL 工具或其他任何程序都能充分利用 Cypher 的全部功能。