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.