Redgraph
A simple RedisGraph library. This gem owes a lot to the existing redisgraph-rb gem, but tries to provide a friendlier interface, similar to the existing Python and Elixir clients.
July 2023 update:
Sadly RedisGraph is no longer in active development. More info here.
Nov 2023 update:
There is an active fork, FalkorDB. AFAIK at this time there are no arm64 builds available.
Dec 2023 update:
FalkorDB has arm64 builds now.
Installation
Add this line to your application's Gemfile:
gem 'redgraph'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install redgraph
Usage
The gem assumes you have a recent version of RedisGraph up and running.
Basic usage:
graph = Redgraph::Graph.new('movies', url: "redis://localhost:6379/1")
=> #<Redgraph::Graph:0x00007f8d5c2b7e38 @connection=#<Redis client v4.2.5 for redis://localhost:6379/1>, @graph_name="movies", @module_version=999999>
Create a couple nodes:
actor = Redgraph::Node.new(label: 'actor', properties: {name: "Al Pacino"})
=> #<Redgraph::Node:0x00007fce3baa0580 @id=nil, @labels=["actor"], @properties={"name"=>"Al Pacino"}>
graph.add_node(actor)
=> #<Redgraph::Node:0x00007fce3baa0580 @id=0, @labels=["actor"], @properties={"name"=>"Al Pacino"}>
film = Redgraph::Node.new(label: 'film', properties: {name: "Scarface"})
=> #<Redgraph::Node:0x00007fce3e8c6c48 @id=nil, @labels=["film"], @properties={"name"=>"Scarface"}>
graph.add_node(film)
=> #<Redgraph::Node:0x00007fce3e8c6c48 @id=1, @labels=["film"], @properties={"name"=>"Scarface"}>
Nodes might have multiple labels, although they're not supported by RedisGraph yet (you can track the feature progress here):
item = Redgraph::Node.new(labels: ['film', 'drama'], properties: {name: "Casino"})
=> #<Redgraph::Node:0x00007fce3bc73308 @id=nil, @labels=["film", "drama"], @properties={"name"=>"Casino"}>
Create an edge between those nodes:
edge = Redgraph::Edge.new(src: actor, dest: film, type: 'ACTOR_IN', properties: {role: "Tony Montana"})
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
graph.add_edge(edge)
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @id=0, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
You can merge nodes - the node will be created only if there isn't another with the same label and properties:
graph.merge_node(film)
=> #<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>
Same with edges:
graph.merge_edge(edge)
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @id=0, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
Find a node by id:
graph.find_node_by_id(1)
=> #<Redgraph::Node:0x00007f8d5c2c6e88 @id=1, @label="film", @properties={"name"=>"Scarface"}>
To get all nodes:
graph.nodes
=> [#<Redgraph::Node:0x00007f8d5c2ee0a0 @id=0, @label="actor", @properties={"name"=>"Al Pacino"}>, #<Redgraph::Node:0x00007f8d5c2edfd8 @id=1, @label="film", @properties={"name"=>"Scarface"}>]
Optional filters that can be combined:
graph.nodes(label: 'actor')
graph.nodes(properties: {name: "Al Pacino"})
graph.nodes(limit: 10, skip: 20)
Counting nodes
graph.count_nodes(label: 'actor')
=> 1
Getting edges:
graph.edges
graph.edges(src: actor, dest: film)
graph.edges(kind: 'FRIEND_OF', limit: 10, skip: 20)
graph.count_edges
Running custom queries
graph.query("MATCH (src)-[edge:FRIEND_OF]->(dest) RETURN src, edge")
NodeModel
You can use the NodeModel mixin for a limited ActiveRecord-like interface:
class Actor
include Redgraph::NodeModel
self.graph = Redgraph::Graph.new("movies", url: $REDIS_URL)
attribute :name
end
And this will give you stuff such as
Actor.count
john = Actor.new(name: "John Travolta")
john.add_to_graph
john.add_relation(type: "ACTED_IN", node: film, properties: {role: "Tony Manero"})
john.reload
john.destroy
Actor.create(name: "Al Pacino")
NodeModel models will automatically set a _type property to keep track of the object class.
You will then be able to run custom queries such as:
Actor.query("MATCH (node) RETURN node ORDER BY node.name")
And the result rows object will be instances of the classes defined by the _type attribute.
Notifications
You can optionally subscribe to redgraph.query ActiveSupport notifications.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run
TEST_REDIS_URL=YOUR-REDIS-URL rake test
to run the tests. Test coverage will be enabled if you set the COVERAGE environment variable to any value.
You can use a TEST_REDIS_URL such as redis://localhost:6379/1. Make sure you're not overwriting important databases.
You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install.
Installing RedisGraph
If you're using an Apple silicon mac you might want to use the docker image: I've had issues compiling the module (OpenMP problems). Just do a:
docker run -p 6380:6379 -it --rm redislabs/redisgraph
or, to try FalkorDB
docker run -p 6380:6379 -it --rm falkordb/falkordb:edge
and then
TEST_REDIS_URL=redis://localhost:6380/0 be rake test
I'm using port 6380 to not interphere with the other redis instance.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/pzac/redgraph.
License
The gem is available as open source under the terms of the MIT License.