Skip to content

Latest commit

 

History

History
161 lines (120 loc) · 4.68 KB

README.md

File metadata and controls

161 lines (120 loc) · 4.68 KB

neo4j.cr

Neo4j connector for Crystal, supporting the Bolt protocol and routing queries to appropriate nodes in your Neo4j cluster.

Installation

Add this to your application's shard.yml:

dependencies:
  neo4j:
    github: jgaskins/neo4j.cr

Usage

First you need to set up a connection:

require "neo4j"

neo4j_uri = URI.parse("bolt://neo4j:password@localhost:7687")

# The `ssl` option defaults to `true` so you don't accidentally send the
# password to your production DB in cleartext.
driver = Neo4j.connect(neo4j_uri, ssl: false)

This will return a cluster driver or a direct driver depending on whether you provided a neo4j:// or bolt:// URI, respectively. neo4j:// can also be specified as bolt+routing://. Both drivers expose the same interface, but the cluster driver will route queries to a different server based on whether you specify that the query is a read or write query.

struct Person
  include Neo4j::Serializable::Node

  getter id: UUID
  getter name: String
  getter email: String
end

driver.session do |session|
  session.read_transaction do |read|
    query = <<-CYPHER
      MATCH (person:Person { name: $name })
      RETURN person
    CYPHER

    read.exec_cast(query, {Person}, name: "Jamie") do |(person)|
      pp person
    end
  end

  session.write_transaction do |write|
    write.execute <<-CYPHER, name: "Jamie"
      MATCH (person:Person { name: $name })
      SET person.login_count = person.login_count + 1
    CYPHER
  end
end

Neo4j::Result

  • type : (Neo4j::Success | Neo4j::Ignored)
    • If you get an Ignored result, it probably means an error occurred. Call connection#reset to get it back to working order.
    • If a query results in a Neo4j::Failure, an exception is raised rather than wrapping it in a Result.
  • data : Array(Array(Neo4j::Type))
    • This is the list of result values. For example, if you RETURN a, b, c from your query, then this will be an array of [a, b, c].

The Result object itself is an Enumerable. Calling Result#each will iterate over the data for you.

Neo4j::Node

These have a 1:1 mapping to nodes in your graph.

  • id : Int32: the node's internal id
    • WARNING: Do not store this id anywhere. These ids can be reused by the database. If you need an application-level unique id, store a UUID on the node. It is useful in querying nodes connected to this one when you already have it in memory, but not beyond that.
  • labels : Array(String): the labels stored on your node
  • properties : Hash(String, Neo4j::Type): the properties assigned to this node

Neo4j::Relationship

  • id: Int32: the relationship's internal id
  • type : String: the type of relationship
  • start : Int32: the internal id for the node on the starting end of this relationship
  • end : Int32: the internal id of the node this relationship points to
  • properties : Hash(String, Neo4j::Type): the properties assigned to this relationship

Neo4j::Value

Represents any data type that can be stored in a Neo4j database and communicated via the Bolt protocol. It's a shorthand for this union type:

Nil |
Bool |
String |
Int8 |
Int16 |
Int32 |
Int64 |
Float64 |
Time |
Neo4j::Point2D |
Neo4j::Point3D |
Neo4j::LatLng |
Array(Neo4j::Value) |
Hash(String, Neo4j::Value) |
Neo4j::Node |
Neo4j::Relationship |
Neo4j::UnboundRelationship |
Neo4j::Path

Mapping to Domain Objects

Similar to JSON.mapping in the Crystal standard library, you can map nodes and relationships to domain objects. For example:

require "uuid"

class User
  include Neo4j::Serializable::Node

  getter uuid : UUID
  getter email : String
  getter name : String
  getter registered_at : Time
end

class Product
  include Neo4j::Serializable::Node

  getter uuid : UUID
  getter name : String
  getter description : String
  getter price : Int32
  getter created_at : Time
end

class CartItem
  include Neo4j::Serializable::Relationship

  getter quantity : Int32
  getter price : Int32
end

Acknowledgements/Credits

The implementation of the wire protocol is heavily based on the MessagePack shard to understand how to serialize and deserialize a binary protocol in Crystal.

Contributing

  1. Fork it ( https://github.com/jgaskins/neo4j.cr/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

  • jgaskins Jamie Gaskins - creator, maintainer