lib/redgraph/graph.rb in redgraph-0.1.2 vs lib/redgraph/graph.rb in redgraph-0.1.3
- old
+ new
@@ -1,9 +1,15 @@
# frozen_string_literal: true
+require_relative "graph/node_methods"
+require_relative "graph/edge_methods"
+
module Redgraph
class Graph
+ include NodeMethods
+ include EdgeMethods
+
attr_accessor :connection, :graph_name
def initialize(graph, redis_options = {})
@graph_name = graph
@connection = Redis.new(redis_options)
@@ -36,144 +42,53 @@
end
# Returns an array of existing labels
#
def labels
- result = query("CALL db.labels()")
+ result = _query("CALL db.labels()")
result.resultset.map(&:values).flatten
end
# Returns an array of existing properties
#
def properties
- result = query("CALL db.propertyKeys()")
+ result = _query("CALL db.propertyKeys()")
result.resultset.map(&:values).flatten
end
# Returns an array of existing relationship types
#
def relationship_types
- result = query("CALL db.relationshipTypes()")
+ result = _query("CALL db.relationshipTypes()")
result.resultset.map(&:values).flatten
end
- # Adds a node. If successul it returns the created object, otherwise false
- #
- def add_node(node)
- result = query("CREATE (n:`#{node.label}` #{quote_hash(node.properties)}) RETURN ID(n)")
- return false if result.stats[:nodes_created] != 1
- id = result.resultset.first["ID(n)"]
- node.id = id
- node
+ # You can run custom cypher queries
+ def query(cmd)
+ _query(cmd).rows
end
- def find_node_by_id(id)
- result = query("MATCH (node) WHERE ID(node) = #{id} RETURN node")
- return nil if result.resultset.empty?
- (node_id, labels, properties) = result.resultset.first["node"]
- attrs = {}
-
- properties.each do |(index, type, value)|
- attrs[get_property(index)] = value
- end
- Node.new(label: get_label(labels.first), properties: attrs).tap do |node|
- node.id = node_id
- end
+ def get_label(id)
+ @labels ||= labels
+ @labels[id] || (@labels = labels)[id]
end
- # Returns nodes. Options:
- #
- # - label: filter by label
- # - properties: filter by properties
- # - limit: number of items
- # - skip: items offset (useful for pagination)
- #
- def nodes(label: nil, properties: nil, limit: nil, skip: nil)
- _label = ":`#{label}`" if label
- _props = quote_hash(properties) if properties
- _limit = "LIMIT #{limit}" if limit
- _skip = "SKIP #{skip}" if skip
-
- cmd = "MATCH (node#{_label} #{_props}) RETURN node #{_skip} #{_limit}"
- result = query(cmd)
-
- result.resultset.map do |item|
- node_from_resultset_item(item["node"])
- end
+ def get_property(id)
+ @properties ||= properties
+ @properties[id] || (@properties = properties)[id]
end
- # Counts nodes. Options:
- #
- # - label: filter by label
- # - properties: filter by properties
- #
- def count_nodes(label: nil, properties: nil)
- _label = ":`#{label}`" if label
- _props = quote_hash(properties) if properties
-
- cmd = "MATCH (node#{_label} #{_props}) RETURN COUNT(node)"
- result = query(cmd)
-
- result.resultset.first["COUNT(node)"]
+ def get_relationship_type(id)
+ @relationship_types ||= relationship_types
+ @relationship_types[id] || (@relationship_types = relationship_types)[id]
end
- # Adds an edge. If successul it returns the created object, otherwise false
- #
- def add_edge(edge)
- result = query("MATCH (src), (dest)
- WHERE ID(src) = #{edge.src.id} AND ID(dest) = #{edge.dest.id}
- CREATE (src)-[e:`#{edge.type}` #{quote_hash(edge.properties)}]->(dest) RETURN ID(e)")
- return false if result.stats[:relationships_created] != 1
- id = result.resultset.first["ID(e)"]
- edge.id = id
- edge
- end
-
- # Finds edges. Options:
- #
- # - type
- # - src
- # - dest
- # - properties
- # - limit
- # - skip
- #
- def edges(type: nil, src: nil, dest: nil, properties: nil, limit: nil, skip: nil)
- _type = ":`#{type}`" if type
- _props = quote_hash(properties) if properties
- _limit = "LIMIT #{limit}" if limit
- _skip = "SKIP #{skip}" if skip
-
- _where = if src || dest
- clauses = [
- ("ID(src) = #{src.id}" if src),
- ("ID(dest) = #{dest.id}" if dest)
- ].compact.join(" AND ")
- "WHERE #{clauses}"
- end
-
- cmd = "MATCH (src)-[edge#{_type} #{_props}]->(dest) #{_where}
- RETURN src, edge, dest #{_skip} #{_limit}"
- result = query(cmd)
-
- result.resultset.map do |item|
- src = node_from_resultset_item(item["src"])
- dest = node_from_resultset_item(item["dest"])
- edge = edge_from_resultset_item(item["edge"])
-
- edge.src = src
- edge.dest = dest
-
- edge
- end
- end
-
private
- def query(cmd)
+ def _query(cmd)
data = @connection.call("GRAPH.QUERY", graph_name, cmd, "--compact")
- QueryResponse.new(data)
+ QueryResponse.new(data, self)
end
def quote_hash(hash)
"{" +
hash.map {|k,v| "#{k}:#{escape_value(v)}" }.join(", ") +
@@ -187,50 +102,7 @@
else
'"' + x.gsub('"', '\"') + '"'
end
end
- def get_label(id)
- @labels ||= labels
- @labels[id] || (@labels = labels)[id]
- end
-
- def get_property(id)
- @properties ||= properties
- @properties[id] || (@properties = properties)[id]
- end
-
- def get_relationship_type(id)
- @relationship_types ||= relationship_types
- @relationship_types[id] || (@relationship_types = relationship_types)[id]
- end
-
- # Builds a Node object from the raw data
- #
- def node_from_resultset_item(item)
- (node_id, labels, props) = item
- attrs = {}
-
- props.each do |(index, type, value)|
- attrs[get_property(index)] = value
- end
- Node.new(label: get_label(labels.first), properties: attrs).tap do |node|
- node.id = node_id
- end
- end
-
- def edge_from_resultset_item(item)
- (edge_id, type_id, _src_id, _dest_id, props) = item
- attrs = {}
-
- props.each do |(index, type, value)|
- attrs[get_property(index)] = value
- end
-
- Edge.new.tap do |edge|
- edge.id = edge_id
- edge.type = get_relationship_type(type_id)
- edge.properties = attrs
- end
- end
end
end