Neo4j client for Golang

neoism - Neo4j client for Go

Neoism Logo

Package neoism is a Go client library providing access to the Neo4j graph database via its REST API.

Status

System Status
Travis CI Travis CI
CircleCI CircleCI
Coveralls Coveralls
Codecov Codecov

This driver is fairly complete, and may now be suitable for general use. The code has an extensive set of integration tests, but little real-world testing. YMMV; use in production at your own risk.

Requirements

Go 1.1 or later is required.

Tested against Neo4j 2.2.4 and Go 1.4.1.

Installation

Development

go get -v github.com/jmcvetta/neoism

Stable

Neoism is versioned using gopkg.in.

Current release is v1

go get gopkg.in/jmcvetta/neoism.v1

Documentation

See GoDoc or Go Walker for automatically generated documentation.

Usage

Connect to Neo4j Database

db, err := neoism.Connect("http://localhost:7474/db/data")

Create a Node

n, err := db.CreateNode(neoism.Props{"name": "Captain Kirk"})

Issue a Cypher Query

// res will be populated with the query results.  It must be a slice of structs.
res := []struct {
		// `json:` tags matches column names in query
		A   string `json:"a.name"` 
		Rel string `json:"type(r)"`
		B   string `json:"b.name"`
	}{}

// cq holds the Cypher query itself (required), any parameters it may have 
// (optional), and a pointer to a result object (optional).
cq := neoism.CypherQuery{
	// Use backticks for long statements - Cypher is whitespace indifferent
	Statement: `
		MATCH (a:Person)-[r]->(b)
		WHERE a.name = {name}
		RETURN a.name, type(r), b.name
	`,
	Parameters: neoism.Props{"name": "Dr McCoy"},
	Result:     &res,
}

// Issue the query.
err := db.Cypher(&cq)

// Get the first result.
r := res[0]

Issue Cypher queries with a transaction

tx, err := db.Begin(qs)
if err != nil {
  // Handle error
}

cq0 := neoism.CypherQuery{
  Statement: `MATCH (a:Account) WHERE a.uuid = {account_id} SET balance = balance + {amount}`,
  Parameters: neoism.Props{"uuid": "abc123", amount: 20},
}
err = db.Cypher(&cq0)
if err != nil {
  // Handle error
}

cq1 := neoism.CypherQuery{
  Statement: `MATCH (a:Account) WHERE a.uuid = {account_id} SET balance = balance + {amount}`,
  Parameters: neoism.Props{"uuid": "def456", amount: -20},
}
err = db.Cypher(&cq1)
if err != nil {
  // Handle error
}

err := tx.Commit()
if err != nil {
  // Handle error
}

Roadmap

Completed:

  • Node (create/edit/relate/delete/properties)
  • Relationship (create/edit/delete/properties)
  • Legacy Indexing (create/edit/delete/add node/remove node/find/query)
  • Cypher queries
  • Batched Cypher queries
  • Transactional endpoint (Neo4j 2.0)
  • Node labels (Neo4j 2.0)
  • Schema index (Neo4j 2.0)
  • Authentication (Neo4j 2.2)

To Do:

  • Streaming API support - see Issue #22
  • Unique Indexes - probably will not expand support for legacy indexing.
  • Automatic Indexes - "
  • High Availability
  • Traversals - May never be supported due to security concerns. From the manual: "The Traversal REST Endpoint executes arbitrary Groovy code under the hood as part of the evaluators definitions. In hosted and open environments, this can constitute a security risk."
  • Built-In Graph Algorithms
  • Gremlin

Testing

Neoism's test suite respects, but does not require, a NEO4J_URL environment variable. By default it assumes Neo4j is running on localhost:7474, with username neo4j and password foobar.

export NEO4J_URL=http://your_user:[email protected]/db/data/
go test -v .

If you are using a fresh untouched Neo4j instance, you can use the included set_neo4j_password.sh script to set the password to that expected by Neoism's tests:

sh set_neo4j_password.sh

Support

Support and consulting services are available from Silicon Beach Heavy Industries.

Contributing

Contributions in the form of Pull Requests are gladly accepted. Before submitting a PR, please ensure your code passes all tests, and that your changes do not decrease test coverage. I.e. if you add new features also add corresponding new tests.

License

This is Free Software, released under the terms of the GPL v3.

Comments
  • Can't connect to GrapheneDB

    Can't connect to GrapheneDB

    Hello there,

    When I try to connect to Graphene DB I get the following output :

    14:40:14.646490 database.go:55: Status 200 trying to connect to http://app****:****@app***.sb02.stations.graphenedb.com:24783
    panic: Invalid database.  Check URI.
    

    I think it comes from the style of the url.

    Cheers.

  • Embedded props

    Embedded props

    Hello there,

    Correct me if I'm wrong but it seems to me that embedded props is something not possible at the moment.

    params := neoism.Props{
        "movieProps": neoism.Props{
            "title": "The Matrix",
        },
    })
    

    I could help doing it if you'd like !

    Cheers.

  • Blog post / driver listing?

    Blog post / driver listing?

    Hey @jmcvetta do you have a blog post about this driver somwhere? Would it make sense to add it to http://neo4j.org/develop/drivers ? Where do you currently use it? Thanks !

  • Examples needed.

    Examples needed.

    Currently the only example code for new users of neoism is embedded in the Go package docs: http://godoc.org/github.com/jmcvetta/neoism

    It would be nice to split that out into an actual example program. Not sure if there is a way to have the contents of a .go file included in the automatic package docs, or if this will have to be copypasta.

  • Add a PropertyKeys() method

    Add a PropertyKeys() method

    It would be great to have the possibility to fetch all property types like it is mentioned in http://docs.neo4j.org/chunked/stable/rest-api-property-values.html

  • repo name conflicts with neo4j itself

    repo name conflicts with neo4j itself

    I know it's probably overly annoying to change it now, but the name is the same as neo4j itself, which is maybe only annoying to people like me who have forked both. If you ever have reason to rename it... please take this into consideration. :)

    Feel free to close this issue.

  • Cypher collection results don't work

    Cypher collection results don't work

    I'll try to submit a patch... this is my query:

    match n:Run-[:scores]->scores
    return n.version, n.released, collect(scores)
    

    The last column is throwing an error.

  • Batch support

    Batch support

    Thinking about how to implement batch operations. Afaik the REST API allows any standard call to be included in a batch operation. A not-yet-existing node can be referred to by its batch ID number. It looks like the batch ID syntax ({ 2 } refers to the result of batch item 2) gets replaced in subsequent commands by the self URL of the previously created entity. Not sure how well this will work for all operations.

    For instance, we can probably add a newly created node to an index by supplying the batch ID syntax in the uri field of the POST. But how can we delete that same index later in the batch, since the actual node ID is required to compose the URL for the DELETE request?

    Should batch support be added to existing Node and Relationship objects? That approach means that some methods, when used in a batch, will always return errors. Maybe it is better to have separate TxNode and TxRelationship objects with a limited subset of methods?

    http://www.mail-archive.com/[email protected]/msg14045.html

    The py2neo driver lets you do index removes in a batch, but they can only refer to a pre-existing node: https://github.com/nigelsmall/py2neo/blob/master/src/py2neo/neo4j.py#L390

  • IncludeStats

    IncludeStats

    IncludeStats=true on a CypherQuery will request that the stats are returned following the execution and the results will be placed in the Stats variable of the query.

  • Add Support for neo4j 2.2.0

    Add Support for neo4j 2.2.0

    Hi, it seems that neoism does not connect to neo4j 2.2.0,I always get the error

    <*errors.errorString | 0xc20802ab00>: {
                s: "Invalid database.  Check URI.",
            }
    

    however seems to work fine with 2.1.x versions

    according to the manual, we need to send an Authorization header now with a base64 encoded user:password string http://neo4j.com/docs/2.2.0/rest-api-security.html

    but it is still possible to deactivate authentication. So that is a workaround for now: http://neo4j.com/docs/2.2.0/security-server.html#security-server-auth

  • GetOrCreateNode doesn't attach a label to a node, as it's signature indicates

    GetOrCreateNode doesn't attach a label to a node, as it's signature indicates

    The GetOrCreateNode (https://github.com/jmcvetta/neoism/blob/master/node.go#L38) function accept a parameter label, which would indicate that a node with the given parameters would be returned (created if necessary) and have the given label attached.

    This isn't the case, because the label variable actually indicates an index, not a label in the REST api. See http://docs.neo4j.org/chunked/stable/rest-api-indexes.html#rest-api-create-node-index for more details.

    Additionally, it seems as though that, although the index that is specified gets created, the node that gets created is not apart of the index?

    For example, consider the following Go:

    package main
    
    import (
        "github.com/jmcvetta/neoism"
    )
    
    func main() {
        db, _ := neoism.Connect("http://localhost:7474/db/data")
    
        db.GetOrCreateNode("Person", "name", neoism.Props{"name": "Matt"})
    }
    

    and, after, running that, consider the following API calls:

    [~] curl http://localhost:7474/db/data/index/node
    {
      "hcHKCYjxGedR" : {
        "template" : "http://localhost:7474/db/data/index/node/hcHKCYjxGedR/{key}/{value}",
        "provider" : "lucene",
        "type" : "exact"
      },
      "Person" : {
        "template" : "http://localhost:7474/db/data/index/node/Person/{key}/{value}",
        "provider" : "lucene",
        "type" : "exact"
      }
    }                                                                                                                    
    [~] curl http://localhost:7474/db/data/index/node/Person
    [ ]
    
  •  #94 - Rename benchmark_test_* files

    #94 - Rename benchmark_test_* files

    Importing the testing package in a file, which is used by the main binary, will pollute the flags package with testing help usage messages. This hinders the usage of the neoism package in a cli application. The file benchmark_test*.go are loading the testing package and are therefore responsible for the flag pollution. To exclude the benchmark_connect helpers one can suffix the files with _test. This will ensure that the benchmark_connect helpers are only loaded during testing and do not pollute the main binary. Another solution would be to introduce a neoism_test package, which would result a massive code reorganization.

  • Permit custom http client

    Permit custom http client

    This PR borrows from #97 in that it allows users of this library to supply their own http.Client instance, but utilises a functional option style of configuration meaning we can leave the Connect method unchanged for the default case, but permit a custom client to be passed via a variadic second argument.

    Our reason for requiring this was to use the HTTPS connector with a self signed certificate where we required creating a custom client with the same certificate in order to communicate from our client to the server.

    This PR also tweaked a couple of lines of Cypher in order to have the tests pass on Neo4j 3.2.x .

  • Create a node with label and properties

    Create a node with label and properties

    I can't add a node with label and property. I only add node with properties and then add label. But if add label fail, I must delete this node. So ID node Increased rapidly. I think that we need a func to add node with label

  • Receiving nested resutls

    Receiving nested resutls

    I have a problem with transferring a response from Neo4j to Golang using neoism.

    The Neo4j response has nested structure and is assembled with Neo4j plugin in the following way.

    I can see that the response is correct in the Neo4j panel. The problem appears when I'm trying to get the response with Golang.

    The following error is received: "Unsupported property type: class pkgName.Dev$NestedReport"

    The problem isn't reproduced in case if only one top-level element is present in the results.

    What is the best way to resolve the issue?

  • get rid of the test.xxx flags in build version

    get rid of the test.xxx flags in build version

    Importing "testing" in files whose name doesn't end _test.go will cause a lot of test.xxx flags in those go program which have both imported "flag" and "github.com/jmcvetta/neoism".

    Here is the example:

    package main
    
    import (
        "os"
        "fmt"
        "flag"
        "github.com/jmcvetta/neoism"
    )
    
    func main() {
        if file, err := os.Open("."); err != nil {
            panic(err)
        } else {
            dir, err := file.Readdir(-1)
            if err != nil {
                panic(err)
            }
    
            for _, fi := range dir {
                fmt.Println(fi.Name())
            }
        }
    
        db, _ := neoism.Connect("http://neo4j:xxx@localhost:7474/db/data")
        fmt.Println(db)
        flag.Parse()
    }
    
    > ./test
    ......
    Usage of ./test:
      -httptest.serve string
            if non-empty, httptest.NewServer serves on this address and blocks
      -test.bench string
            regular expression to select benchmarks to run
      -test.benchmem
            print memory allocations for benchmarks
      -test.benchtime duration
            approximate run time for each benchmark (default 1s)
      -test.blockprofile string
            write a goroutine blocking profile to the named file after execution
      -test.blockprofilerate int
            if >= 0, calls runtime.SetBlockProfileRate() (default 1)
      -test.count n
            run tests and benchmarks n times (default 1)
    ......
    

    And I got the "httptest.serve" left even if I removed all the test.go files in neoism. This is really annoying, so I hope it will be fixed soon. Thanks for your effort.

    ArkBriar 2016-4-29

Neo4j Rest API Client for Go lang

neo4j.go Implementation of client package for communication with Neo4j Rest API. For more information and documentation please read Godoc Neo4j Page s

Nov 9, 2022
Quick demo of Neo4j 4.4 new impersonation feature in Go

Neo4j 4.4 impersonation demo This is a simple application that demonstrates how to configure impersonation. Database setup Start a Neo4j server. On th

Dec 13, 2021
Golang client for redislabs' ReJSON module with support for multilple redis clients (redigo, go-redis)

Go-ReJSON - a golang client for ReJSON (a JSON data type for Redis) Go-ReJSON is a Go client for ReJSON Redis Module. ReJSON is a Redis module that im

Dec 25, 2022
redis client implement by golang, inspired by jedis.

godis redis client implement by golang, refers to jedis. this library implements most of redis command, include normal redis command, cluster command,

Dec 6, 2022
Go Memcached client library #golang

About This is a memcache client library for the Go programming language (http://golang.org/). Installing Using go get $ go get github.com/bradfitz/gom

Jan 8, 2023
Type-safe Redis client for Golang

Redis client for Golang ❤️ Uptrace.dev - distributed traces, logs, and errors in one place Join Discord to ask questions. Documentation Reference Exam

Jan 1, 2023
Type-safe Redis client for Golang

Redis client for Golang ❤️ Uptrace.dev - distributed traces, logs, and errors in one place Join Discord to ask questions. Documentation Reference Exam

Jan 4, 2023
HDFS for Go - This is a native golang client for hdfs.

HDFS for Go This is a native golang client for hdfs. It connects directly to the namenode using the protocol buffers API. It tries to be idiomatic by

Dec 24, 2022
A CouchDB client in Go(Golang)

pillow pillow is a CouchDB client in Go(Golang). Resources Installation Usage Example Installation Install pillow as you normally would for any Go pac

Nov 9, 2022
Redis client for Golang
Redis client for Golang

Redis client for Golang To ask questions, join Discord or use Discussions. Newsl

Dec 23, 2021
Redis client for Golang
Redis client for Golang

Redis client for Golang Discussions. Newsletter to get latest updates. Documentation Reference Examples RealWorld example app Other projects you may l

Dec 30, 2021
Aerospike Client Go

Aerospike Go Client An Aerospike library for Go. This library is compatible with Go 1.9+ and supports the following operating systems: Linux, Mac OS X

Dec 14, 2022
Couchbase client in Go

A smart client for couchbase in go This is a unoffical version of a Couchbase Golang client. If you are looking for the Offical Couchbase Golang clien

Nov 27, 2022
Go client library for Pilosa

Go Client for Pilosa Go client for Pilosa high performance distributed index. What's New? See: CHANGELOG Requirements Go 1.12 and higher. Install Down

Dec 3, 2022
Go client for Redis

Redigo Redigo is a Go client for the Redis database. Features A Print-like API with support for all Redis commands. Pipelining, including pipelined tr

Jan 1, 2023
Go Redis Client

xredis Built on top of github.com/garyburd/redigo with the idea to simplify creating a Redis client, provide type safe calls and encapsulate the low l

Sep 26, 2022
godis - an old Redis client for Go

godis Implements a few database clients for Redis. There is a stable client and an experimental client, redis and exp, respectively. To use any of the

Apr 16, 2022
Google Go Client and Connectors for Redis

Go-Redis Go Clients and Connectors for Redis. The initial release provides the interface and implementation supporting the (~) full set of current Red

Oct 25, 2022
Redis client library for Go

go-redis go-redis is a Redis client library for the Go programming language. It's built on the skeleton of gomemcache. It is safe to use by multiple g

Nov 8, 2022