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