Have ideas to improve npm?Join in the discussion! »

    neogoose
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.0 • Public • Published

    neogoose

    Node.js Neo4j OGM inspired by Mongoose & GraphQL

    Node.js CI npm version

    neogoose

    TLDR

    Use GraphQL schema language to define Models. On Model CRUD input validated & output resolved through a generated GraphQL schema. Modularize your neo4js-graphql-js augmented schema with the additional power of an OGM for further database operations.

    Models are not designed to support querying relationships use a session for this. This library is designed to place a CRUD api over nodes. You can also create an Executable schema to execute more complex queries.

    Installation

    First install Node.js, then start Neo4j & finally...

    $ npm install neogoose
    

    neo4j-driver and graphql are peerDependencies you may need to install them too.

    $ npm install neo4j-driver graphql
    

    Importing

    const neogoose = require("neogoose");

    Connecting

    await neogoose.connect("neo4j://localhost");

    Creating Multiple connections

    const connection1 = await neogoose.createConnection("neo4j://1.1.1.1");
    const connection2 = await neogoose.createConnection("neo4j://2.2.2.2");

    Disconnecting

    await neogoose.disconnect();

    Defining a Model

    Models are defined using GraphQL schema language.

    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                type User {
                    id: ID!
                    name: String!
                    email: String!
                }
            `
        }
    );

    Creating a session

    await neogoose.connect("neo4j://localhost");
     
    // https://neo4j.com/developer/javascript/
    const session = await neogoose.session();

    Retrieving a model

    const user = neogoose.model("User");

    Executable schema

    Compile your models into an neo4js-graphql-js augmented schema

    const schema = neogoose.makeAugmentedSchema();

    Transforms made before calling makeAugmentedSchema

    1. constraint directives removed
    2. Validation directives removed

    ⚠ All other schema directives here are ignored in neogoose land

    Query

    Used with;

    1. findOne
    2. findMany
    3. updateOne
    4. updateMany
    5. deleteOne
    6. deleteMany
    7. count

    Equality

    const dan = await User.findOne({
        name: "Dan",
    });

    $or

    const users = await User.findMany({
        $or: [
            { name: "Dan" },
            { name: "Daniel" }
        ],
    });

    $and

    const users = await User.findMany({
        $and: [
            { name: "Dan" },
            { repo: "neogoose" }
        ],
    });

    $regex

    const users = await User.findMany({
        name: {
            $regex: '(?i)d.*' // equal to new Regex("^d", "i")
        },
    });

    ⚠ Javascript regex not supported use regex stated here

    $in

    const users = await User.findMany({
        name: {
            $in: ["Dan", "Daniel"]
        },
    });

    Comparison Operators

    1. $eq
    2. $gt
    3. $gte
    4. $in
    5. $lt
    6. $lte
    7. $ne
    8. $nin

    Logical Operators

    1. $and
    2. $or

    Evaluation Operators

    1. $regex

    Skip/Limit

    Used with

    1. findMany
    2. updateMany
    3. deleteMany
    const paginatedUsers = await User.findMany(
        query,
        { skip: 30, limit: 10 }
    );

    Creating nodes

    1. create
    2. createMany
    const user = await User.create(
        {
            id: uuid(),
            name: "Dan",
            email: "email@email.com"
        },
        {
            return: true
        }
    );
     
    await User.createMany([ ... ])

    Find nodes

    1. findMany
    2. findOne
    const query = {
        name: "Dan",
    };
     
    const users = await User.findMany(query);
     
    const dan = await User.findOne(query);

    Update nodes

    1. updateOne
    2. updateMany
    const query = {
        name: "Dan",
    };
     
    const update = {
        name: "naD"
    };
     
    await User.updateMany(query, update);
     
    const user = await User.updateOne(
        query,
        update,
        { return: true } // use to return the updated node
    );

    Using $set

    Regular update will replace all properties use $set to += properties on the node

    const query = {
        name: "Dan",
    };
     
    const update = {
        repo: "neogoose"
    };
     
    const user = await User.updateOne(
        query,
        { $set: update },
        { return: true }
    );
     
    user.name // Dan
    user.repo // neogoose

    Deleting properties

    $set to null

    const user = await User.updateOne(
        query,
        { $set: { loggedIn: null }
    );

    Delete nodes

    1. deleteOne
    2. deleteMany
    const query = {
        name: "Dan",
    };
     
    await User.deleteOne(
        query, 
        {
            detach: true // set to true for DETACH DELETE, delete nodes and relationships
        }
    );
     
    const users = await User.deleteMany(
        query, 
        { return: true } // use to return the deleted nodes
    );

    Count nodes

    1. count
    const query = {
        name: "Dan",
    };
     
    const userCount = await User.count(
        query
    );

    Resolvers

    Records returned from your Neo4j instance are 'pulled' through a GraphQL schema, you can use Resolvers to achieve 'virtuals' on a model.

    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                type User {
                    id: ID!
                    name: String!
                    email: String!
                    resolved: String!
                }
            `,
            resolvers: {
                User: {
                    id: (root) => root.id, // Not needed
                    resolved: () => "I was Resolved"
                }
            }
        }
    );

    Selection Set

    Select more than Autogenerated Selection Set works well with Resolvers and complex nested types, Used with;

    1. findOne
    2. findMany
    3. updateOne
    4. updateMany
    5. deleteOne
    6. deleteMany
    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                type NestedType {
                    abc: String
                }
     
                type User {
                    id: ID!
                    name: String!
                    email: String!
                    nested: NestedType!
                }
            `
        }
    );
     
    const selectionSet = `
        {
            id
            name
            email
            nested {
                abc
            }
        }
    `
     
    const dan = await User.findOne(
        {
            name: "Dan",
        },
        { selectionSet }
    );
     
    // exists(dan.nested.abc) === true

    Autogenerated Selection Set

    ⚠ If you don't specify Selection Set an auto generated one will be made based on the provided type.

    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                type NestedType {
                    abc: String
                }
     
                type User {
                    id: ID!
                    name: String!
                    email: String!
                    nested: NestedType!
                }
            `
        }
    );
     
    const AUTO_SELECTION_SET = `
        {
            id
            name
            email
            nested # ⚠ ERROR
        }
    `

    Validation

    Built in support for @Validation directive.

    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                input UserProperties {
                    id: ID! 
                    name: String
                    email: String
                }
     
                type User @Validation(properties: UserProperties) {
                    id: ID!
                    name: String!
                    email: String!
                }
            `
        }
    );

    Auto Validation

    ⚠ If you don't specify @Validation an auto generated input will be made based on the provided type. Nested input types are not supported!

    Before

    {
        typeDefs: `
            type User  {
                id: ID!
                name: String!
                email: String!
            }
        `
    }

    After

    The below is representing the Models auto generated schema if you don't provide @Validation directive.

    {
        typeDefs: `
            input AUTO_GENERATED { # Default if you don't specify properties
                id: ID!
                name: String!
                email: String!  
            }
     
            type User @Validation(properties: AUTO_GENERATED) {
                id: ID!
                name: String!
                email: String!
            }
        `
    }

    Directives

    Built in support for graphql-constraint-directive.

    const User = neogoose.model(
        "User",
        {
            typeDefs: `
                input UserProperties {
                    id: ID! @constraint(minLength: 5, format: "uid")
                    name: String @constraint(minLength: 5)
                    email: String @constraint(minLength: 5, format: "email")
                }
     
                type User @Validation(properties: UserProperties) {
                    id: ID!
                    name: String!
                    email: String!
                }
            `
        }
    );

    @constraint directives are removed before augmented schema generation.

    Install

    npm i neogoose

    DownloadsWeekly Downloads

    0

    Version

    1.0.0

    License

    MIT

    Unpacked Size

    78.8 kB

    Total Files

    78

    Last publish

    Collaborators

    • avatar