安装

您可以将 OGM 安装到新的或现有的 Node.js 项目中,方法类似于安装 Neo4j GraphQL 库。它具有以下依赖项

  • @neo4j/graphql-ogm: OGM 包。

  • graphql: Neo4j GraphQL 库用来生成模式并执行查询和突变的包。

  • neo4j-driver: 用于 JavaScript 的官方 Neo4j 驱动程序包,用于与数据库交互。

npm install @neo4j/graphql-ogm graphql neo4j-driver

使用示例

以下是一些使用 OGM 的示例。

自定义解析器

OGM 可以访问 Neo4j GraphQL 库无法访问的某些字段。在处理此类字段时,通常的做法是使用 OGM 创建自定义解析器。例如,您可以有一个用 @private 指令标记的 password 字段,以及一个用于创建带有密码的用户的自定义解析器。

执行以下操作以创建示例应用程序目录并创建一个新项目

mkdir ogm-custom-resolvers-example
cd ogm-custom-resolvers-example
npm init es6 --yes
touch index.js

安装依赖项

npm install @neo4j/graphql-ogm graphql neo4j-driver @apollo/server

假设在 "neo4j://localhost:7687" 处有一个正在运行的 Neo4j 数据库,用户名为 "username",密码为 "password",在空的 index.js 文件中,添加以下代码

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { Neo4jGraphQL } from "@neo4j/graphql";
import { OGM } from "@neo4j/graphql-ogm";
import neo4j from "neo4j-driver";

import { createJWT, comparePassword } from "./utils.js"; // example util function, more information below

const driver = neo4j.driver(
    "neo4j://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const typeDefs = `#graphql
    type User {
        id: ID @id
        username: String!
        password: String! @private
    }

    type Mutation {
        signUp(username: String!, password: String!): String! ### JWT
        signIn(username: String!, password: String!): String! ### JWT
    }
`;

const ogm = new OGM({ typeDefs, driver });
const User = ogm.model("User");

const resolvers = {
    Mutation: {
        signUp: async (_source, { username, password }) => {
            const [existing] = await User.find({
                where: {
                    username,
                },
            });

            if (existing) {
                throw new Error(`User with username ${username} already exists!`);
            }

            const { users } = await User.create({
                input: [
                    {
                        username,
                        password,
                    }
                ]
            });

            return createJWT({ sub: users[0].id });
        },

        signIn: async (_source, { username, password }) => {
            const [user] = await User.find({
                where: {
                    username,
                },
            });

            if (!user) {
                throw new Error(`User with username ${username} not found!`);
            }

            const correctPassword = await comparePassword(password, user.password);

            if (!correctPassword) {
                throw new Error(
                    `Incorrect password for user with username ${username}!`
                );
            }

            return createJWT({ sub: user.id });
        },
    },
};


const neoSchema = new Neo4jGraphQL({
    typeDefs,
    driver,
    resolvers,
    features: {
        authorization: {
            key: "secret",
        },
    },
});

async function main() {
    await ogm.init();

    const server = new ApolloServer({
        schema: await neoSchema.getSchema(),
    });

    const { url } = await startStandaloneServer(server, {
        listen: { port: 4000 },
        context: async ({ req }) => ({
            token: req.headers.authorization,
        }),
    });

    console.log(`🚀 Server ready at ${url}`);
}

main();

在同一个目录中创建文件 utils.js。安装额外的依赖项

npm install bcrypt jsonwebtoken

将以下代码添加到 utils.js

import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";

export function createJWT(data) {
    return new Promise((resolve, reject) => {
        jwt.sign(data, "<insert your JWT secret here!>", (err, token) => {
            if (err) {
                return reject(err);
            }

            return resolve(token);
        });
    });
}

export function comparePassword(plainText, hash) {
    return new Promise((resolve, reject) => {
        bcrypt.compare(plainText, hash, (err, result) => {
            if (err) {
                return reject(err);
            }

            return resolve(result);
        });
    });
}

util 函数 createJWTcomparePassword 的代码只是一个示例。请根据您的用例进行调整。

回到命令行,运行以下命令启动您的服务器

node index.js

您应该看到以下输出

🚀 Server ready at http://localhost:4000/

您可以对 GraphQL API 执行 signUp 突变以注册,但如果您尝试通过同一个 API 查询用户,则密码字段将不可用。

REST API

此示例演示了如何在不公开 Neo4j GraphQL API 终结点的情况下使用 OGM。它启动一个 Express 服务器,并使用 OGM 与通过 REST 终结点公开的 Neo4j GraphQL 库进行交互。

执行以下操作以创建示例应用程序目录和一个新项目

mkdir ogm-rest-example
cd ogm-rest-example
npm init es6 --yes
touch index.js

安装依赖项

npm install @neo4j/graphql-ogm graphql neo4j-driver express

假设在 "neo4j://localhost:7687" 处有一个正在运行的 Neo4j 数据库,用户名为 "username",密码为 "password",在空的 index.js 文件中,添加以下代码

import express from "express";
import { OGM } from "@neo4j/graphql-ogm";
import neo4j from "neo4j-driver";

const driver = neo4j.driver(
  "bolt://localhost:7687",
  neo4j.auth.basic("username", "password")
);

const typeDefs = `
    type User {
        id: ID
        name: String
    }
`;

const ogm = new OGM({
  typeDefs,
  driver,
  features: { filters: { String: { MATCHES: true } } },
});

const User = ogm.model("User");

const app = express();

app.get("/users", async (req, res) => {
  const { search, offset, limit, sort } = req.query;

  const regex = search ? `(?i).*${search}.*` : null;

  const users = await User.find({
    where: { name_MATCHES: regex },
    options: {
      offset,
      limit,
      sort,
    },
  });

  return res.json(users).end();
});

const port = 4000;

ogm.init().then(() => {
  app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}/users`);
  });
});

在您的应用程序目录中,您可以运行此应用程序

node index.js

您应该看到以下输出

Example app listening at http://localhost:4000/users

REST API 现在应该在 http://localhost:4000 处可用,并有一个可用的路由 /users