Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jgaskins/neo4j.cr
Pure-Crystal implementation of Neo4j's Bolt protocol
https://github.com/jgaskins/neo4j.cr
graph-database neo4j neo4j-driver
Last synced: about 2 months ago
JSON representation
Pure-Crystal implementation of Neo4j's Bolt protocol
- Host: GitHub
- URL: https://github.com/jgaskins/neo4j.cr
- Owner: jgaskins
- License: mit
- Created: 2017-10-26T15:07:06.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2023-09-21T20:38:48.000Z (over 1 year ago)
- Last Synced: 2024-10-25T01:40:18.782Z (about 2 months ago)
- Topics: graph-database, neo4j, neo4j-driver
- Language: Crystal
- Homepage:
- Size: 209 KB
- Stars: 30
- Watchers: 4
- Forks: 7
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# neo4j.cr
Neo4j connector for Crystal, supporting the [Bolt protocol](https://neo4j.com/docs/bolt/current/) and routing queries to appropriate nodes in your [Neo4j cluster](https://neo4j.com/docs/bolt/current/driver-api/#client-side-routing).
## Installation
Add this to your application's `shard.yml`:
```yaml
dependencies:
neo4j:
github: jgaskins/neo4j.cr
```## Usage
First you need to set up a connection:
```crystal
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.
```crystal
struct Person
include Neo4j::Serializable::Nodegetter id: UUID
getter name: String
getter email: String
enddriver.session do |session|
session.read_transaction do |read|
query = <<-CYPHER
MATCH (person:Person { name: $name })
RETURN person
CYPHERread.exec_cast(query, {Person}, name: "Jamie") do |(person)|
pp person
end
endsession.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:
```crystal
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:
```crystal
require "uuid"class User
include Neo4j::Serializable::Nodegetter uuid : UUID
getter email : String
getter name : String
getter registered_at : Time
endclass Product
include Neo4j::Serializable::Nodegetter uuid : UUID
getter name : String
getter description : String
getter price : Int32
getter created_at : Time
endclass CartItem
include Neo4j::Serializable::Relationshipgetter quantity : Int32
getter price : Int32
end
```## Acknowledgements/Credits
The implementation of the wire protocol is _heavily_ based on the [MessagePack shard](https://github.com/crystal-community/msgpack-crystal) 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](https://github.com/jgaskins) Jamie Gaskins - creator, maintainer