故障排除

本章包含常见的故障排除步骤。此外,还提供了一个常见问题解答部分,您可能在其中找到问题的答案。

调试日志记录

对于@neo4j/graphql

@neo4j/graphql使用debug库进行调试级别日志记录。您可以在运行时将环境变量DEBUG设置为@neo4j/graphql:*,以开启所有调试日志记录。例如

命令行

DEBUG=@neo4j/graphql:* node src/index.js

或者,如果您正在调试特定功能,您可以指定多个命名空间以隔离某些日志行

  1. @neo4j/graphql:* - 记录所有内容

  2. @neo4j/graphql:auth - 记录授权标头和令牌提取的状态,以及 JWT 的解码

  3. @neo4j/graphql:graphql - 记录 GraphQL 查询和变量

  4. @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 {
        title: String!
    }
`;

const driver = neo4j.driver(
    "bolt://localhost: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 {
        title: String!
    }
`;

const driver = neo4j.driver(
    "bolt://localhost: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}`);
    });
});

常见问题解答

本章包含常见问题及其解决方案。

我已从<1.1.0 升级,但我的DateTime字段无法按预期排序

由于版本小于 1.1.0 中的错误,您的DateTime字段可能会存储在数据库中,作为字符串而不是时间值。您应该使用 Cypher 查询在数据库中对这些属性进行重写。对于受影响的节点具有标签“Movie”且受影响的属性为“timestamp”的示例,您可以使用以下 Cypher 执行此操作

MATCH (m:Movie)
WHERE apoc.meta.type(m.timestamp) = "STRING"
SET m.timestamp = datetime(m.timestamp)
RETURN m

我已创建了一些数据,然后去查询它,但它不存在

如果您使用因果集群或 Aura 专业版实例,则创建的数据可能尚未出现在下一次 GraphQL 查询连接到的服务器上。

我的更新和创建输入中的_emptyInput是什么?

如果您定义的类型仅包含自动生成和/或关系属性,则_emptyInput将出现在您的更新和创建输入中。这是一个占位符属性,因此,在更新或创建中为其赋值都不会在节点上对其赋值。如果您添加用户提供的属性,_emptyInput将被删除。

以下示例将创建具有_emptyInput的输入

type Cookie {
    id: ID! @id
    owner: Owner!  @relationship(type: "HAS_OWNER", direction: OUT)
    # f: String # If you don't want _emptyInput, uncomment this line.
}

我的图中没有强制执行关系可空性

目前,并且考虑到以下 typeDefs,Neo4j GraphQL 将在创建和更新一对一关系时强制执行基数,例如以下电影导演字段

type Movie {
    title: String!
    director: Person! @relationship(type: "DIRECTED", direction: IN)
    actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}

type Person {
    name: String!
}

但是,目前还没有机制来支持验证演员关系。此外,如果您在一次变异中创建电影和导演,则存在已知的限制

mutation {
  createMovies(
    input: [
      {
        title: "Forrest Gump"
        director: { create: { node: { name: "Robert Zemeckis" } } }
      }
    ]
  ) {
    movies {
      title
      director {
        name
      }
    }
  }
}

然后删除导演节点

mutation {
  deletePeople(where: { name: "Robert Zemeckis" }) {
    nodesDeleted
  }
}

即使模式声明所有电影必须有导演,因此从技术上讲电影节点无效,也不会抛出错误。

最后,我们不会在联合或接口关系上强制执行关系基数。

安全

本节介绍安全注意事项和已知问题。

授权未针对空匹配触发

如果查询没有结果,则不会触发授权过程。这意味着结果将为空,而不是抛出身份验证错误。即使无法访问数据本身,未经授权的用户仍然可以辨别数据库中是否存在特定类型。