故障排除
|
这是 GraphQL Library 7 版本的文档。对于长期支持 (LTS) 版本 5,请参考 GraphQL Library 5 LTS 版本。 |
本章包含常见的故障排除步骤。此外,还有一个 常见问题解答 (FAQs) 部分,您可能在那里找到问题的答案。
调试日志
针对 @neo4j/graphql
@neo4j/graphql 使用 debug 库进行调试级别的日志记录。您可以在运行时设置环境变量 DEBUG 为 @neo4j/graphql:* 来开启所有调试日志。例如:
命令行
DEBUG=@neo4j/graphql:* node src/index.js
或者,如果您正在调试特定功能,可以指定多个命名空间来隔离某些日志行:
-
@neo4j/graphql:*- 记录所有信息 -
@neo4j/graphql:auth- 记录授权头和令牌提取的状态,以及 JWT 的解码过程 -
@neo4j/graphql:graphql- 记录 GraphQL 查询和变量 -
@neo4j/graphql:execution- 记录执行前的 Cypher 语句和 Cypher 参数,以及执行摘要
构造函数
您也可以通过在构造函数中将 debug 参数设置为 true 来启用库中的所有调试日志。
const { Neo4jGraphQL } = require("@neo4j/graphql");
const neo4j = require("neo4j-driver");
const { ApolloServer } = require("apollo-server");
const typeDefs = `
type Movie @node {
title: String!
}
`;
const driver = neo4j.driver(
"bolt://:7687",
neo4j.auth.basic("username", "password")
);
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
debug: true,
});
针对 @neo4j/introspector
@neo4j/introspector 有其自己的调试日志命名空间,您可以通过以下方式开启其日志记录:
DEBUG=@neo4j/introspector node src/index.js
阅读更多关于 内省器 (introspector) 的信息。
查询调优
希望您不需要进行任何查询调优,但如果需要,Neo4j GraphQL 库允许您在请求上下文中设置完整的查询选项数组。
您可以阅读更多关于可用查询选项的信息:Cypher 手册 → 查询选项。
请仅在您了解操作后果的情况下设置这些选项。
例如,将 "runtime" 选项设置为 "interpreted":
const { Neo4jGraphQL } = require("@neo4j/graphql");
const neo4j = require("neo4j-driver");
const { ApolloServer } = require("apollo-server");
const typeDefs = `
type Movie @node {
title: String!
}
`;
const driver = neo4j.driver(
"bolt://:7687",
neo4j.auth.basic("username", "password")
);
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
});
neoSchema.getSchema().then((schema) => {
const server = new ApolloServer({
schema,
context: ({ req }) => ({
req,
cypherQueryOptions: {
runtime: "interpreted",
},
}),
});
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
});
常见问题解答 (FAQs)
本章包含常见问题及其解决方案。
我从 <1.1.0 版本升级,但我的 DateTime 字段排序不符合预期
由于 1.1.0 之前的版本存在一个 bug,您的 DateTime 字段可能以字符串形式而非时间值存储在数据库中。您应该使用 Cypher 查询重写数据库中的这些属性。例如,如果受影响的节点标签为 "Movie",受影响的属性为 "timestamp",您可以使用以下 Cypher 语句进行处理:
MATCH (m:Movie)
WHERE apoc.meta.type(m.timestamp) = "STRING"
SET m.timestamp = datetime(m.timestamp)
RETURN m
我创建了一些数据,然后去查询,但数据不存在
如果您使用因果集群 (causal cluster) 或 Aura Professional 实例,创建的数据可能尚未同步到下一次 GraphQL 查询所连接的服务器上。
我的更新和创建输入中的 _emptyInput 是什么?
如果您定义的类型仅包含自动生成的属性和/或关系属性,则 _emptyInput 会出现在您的更新和创建输入中。它是一个占位符属性,因此在更新或创建时为其赋值不会改变节点上的任何值。如果您添加了用户定义的属性,_emptyInput 将会被移除。
以下示例将创建包含 _emptyInput 的输入:
type Cookie @node {
id: ID! @id
owner: Owner! @relationship(type: "HAS_OWNER", direction: OUT)
# f: String # If you don't want _emptyInput, uncomment this line.
}
我的图谱中没有强制执行关系的可空性 (nullability)
目前,针对下方的 typeDefs,Neo4j GraphQL 在创建和更新一对一关系(如以下的电影导演字段)时会强制执行基数约束:
type Movie @node {
title: String!
director: Person! @relationship(type: "DIRECTED", direction: IN)
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}
type Person @node {
name: String!
}
然而,目前还没有机制来支持验证 "actors" 关系。此外,还有一个已知的局限性:如果您在一次变更 (mutation) 中同时创建电影和导演:
mutation {
createMovies(
input: [
{
title: "Forrest Gump"
director: { create: { node: { name: "Robert Zemeckis" } } }
}
]
) {
movies {
title
director {
name
}
}
}
}
然后删除该导演节点:
mutation {
deletePeople(where: { name: { eq: "Robert Zemeckis" } }) {
nodesDeleted
}
}
尽管 schema 规定所有电影必须有一个导演,从而在技术上使电影节点失效,但系统不会抛出任何错误。
最后,我们不会在联合 (union) 或接口 (interface) 关系上强制执行关系基数约束。
安全性
本节描述安全注意事项和已知问题。
空匹配时不会触发授权
如果查询没有产生结果,则 授权 (Authorization) 过程将不会被触发。这意味着结果将为空,而不是抛出身份验证错误。未经授权的用户可能会据此推断数据库中是否存在某种类型的节点,即使他们无法访问数据本身。