lib/redgraph/graph.rb in redgraph-0.1.1 vs lib/redgraph/graph.rb in redgraph-0.1.2
- old
+ new
@@ -47,10 +47,17 @@
def properties
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.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
@@ -88,22 +95,29 @@
cmd = "MATCH (node#{_label} #{_props}) RETURN node #{_skip} #{_limit}"
result = query(cmd)
result.resultset.map do |item|
- (node_id, labels, props) = item["node"]
- 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
+ node_from_resultset_item(item["node"])
end
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)"]
+ 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}
@@ -112,10 +126,49 @@
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)
data = @connection.call("GRAPH.QUERY", graph_name, cmd, "--compact")
QueryResponse.new(data)
@@ -128,12 +181,13 @@
end
def escape_value(x)
case x
when Integer then x
+ when NilClass then "''"
else
- "'#{x}'"
+ '"' + x.gsub('"', '\"') + '"'
end
end
def get_label(id)
@labels ||= labels
@@ -141,8 +195,42 @@
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