Class: Tina4::Drivers::UltipaGraphDriver
- Inherits:
-
GraphAdapter
- Object
- GraphAdapter
- Tina4::Drivers::UltipaGraphDriver
- Defined in:
- lib/tina4/drivers/ultipa_graph_driver.rb
Constant Summary collapse
- UNBOUNDED_CONNECT_TIMEOUT =
nil (unbounded) is mapped to a very large finite deadline for the gRPC driver, whose connect deadline is Time.now + connect_timeout (a 0 there would mean "do not wait", not "wait forever").
315_360_000
Instance Method Summary collapse
- #add_edge(from_id, to_id, type, properties = nil) ⇒ Object
-
#add_node(label, properties = nil) ⇒ Object
-- portable node/edge/traverse core (GQL) --------------------------.
- #close ⇒ Object
- #delete_node(node_id) ⇒ Object
- #execute(text, params = nil) ⇒ Object
- #get_node(node_id) ⇒ Object
-
#initialize(graph_url, username: "", password: "") ⇒ UltipaGraphDriver
constructor
~10 years.
- #neighbors(node_id, direction: "both", edge_type: nil, limit: 100) ⇒ Object
-
#query(text, params = nil) ⇒ Object
-- connection + raw pass-through -----------------------------------.
- #traverse(start_id, depth: 1, direction: "both", edge_type: nil, limit: 1000) ⇒ Object
- #update_node(node_id, properties) ⇒ Object
Methods inherited from GraphAdapter
Constructor Details
#initialize(graph_url, username: "", password: "") ⇒ UltipaGraphDriver
~10 years
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 27 def initialize(graph_url, username: "", password: "") @url = graph_url @last_error = nil timeout = Tina4.resolve_graph_connect_timeout @client = Tina4Ultipa::Client.new( host: graph_url.host, port: graph_url.port, username: graph_url.username || (username unless username.to_s.empty?), password: graph_url.password || (password unless password.to_s.empty?), graph: graph_url.graph, connect_timeout: timeout.nil? ? UNBOUNDED_CONNECT_TIMEOUT : timeout, use_tls: graph_url.use_tls, ) end |
Instance Method Details
#add_edge(from_id, to_id, type, properties = nil) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 64 def add_edge(from_id, to_id, type, properties = nil) # id(e) requires EDGE_ID enabled on the Ultipa graph # (`ALTER GRAPH <g> SET EDGE_ID ENABLED`), a one-time per-graph setting. prop_map, params = prop_clause(properties) params["from_id"] = from_id params["to_id"] = to_id gql = "MATCH (a), (b) WHERE id(a) = $from_id AND id(b) = $to_id " \ "INSERT (a)-[e:`#{type}` #{prop_map}]->(b) " \ "RETURN id(e) AS id, type(e) AS type, id(a) AS f, id(b) AS t, " \ "properties(e) AS props" rows = run(gql, params: params, read_only: false).dicts return nil if rows.empty? row = rows[0] Tina4::GraphEdge.new( id: row["id"], type: row["type"], from: row["f"], to: row["t"], properties: row["props"] || {}, ) end |
#add_node(label, properties = nil) ⇒ Object
-- portable node/edge/traverse core (GQL) --------------------------
56 57 58 59 60 61 62 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 56 def add_node(label, properties = nil) prop_map, params = prop_clause(properties) gql = "INSERT (n:`#{label}` #{prop_map}) " \ "RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props" rows = run(gql, params: params, read_only: false).dicts node_from_row(rows[0]) end |
#close ⇒ Object
140 141 142 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 140 def close @client.close end |
#delete_node(node_id) ⇒ Object
103 104 105 106 107 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 103 def delete_node(node_id) run("MATCH (n) WHERE id(n) = $id DETACH DELETE n", params: { "id" => node_id }, read_only: false) true end |
#execute(text, params = nil) ⇒ Object
49 50 51 52 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 49 def execute(text, params = nil) result = run(text, params: params, read_only: false) Tina4::GraphResult.new(records: result.dicts, columns: result.columns) end |
#get_node(node_id) ⇒ Object
84 85 86 87 88 89 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 84 def get_node(node_id) gql = "MATCH (n) WHERE id(n) = $id " \ "RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props" rows = run(gql, params: { "id" => node_id }, read_only: true).dicts node_from_row(rows[0]) end |
#neighbors(node_id, direction: "both", edge_type: nil, limit: 100) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 109 def neighbors(node_id, direction: "both", edge_type: nil, limit: 100) edge = edge_type ? ":`#{edge_type}`" : "" pattern = case direction when "out" then "(n)-[#{edge}]->(m)" when "in" then "(n)<-[#{edge}]-(m)" else "(n)-[#{edge}]-(m)" end gql = "MATCH #{pattern} WHERE id(n) = $id " \ "RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props " \ "LIMIT #{limit.to_i}" rows = run(gql, params: { "id" => node_id }, read_only: true).dicts rows.map { |row| node_from_row(row) } end |
#query(text, params = nil) ⇒ Object
-- connection + raw pass-through -----------------------------------
44 45 46 47 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 44 def query(text, params = nil) result = run(text, params: params, read_only: true) Tina4::GraphResult.new(records: result.dicts, columns: result.columns) end |
#traverse(start_id, depth: 1, direction: "both", edge_type: nil, limit: 1000) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 123 def traverse(start_id, depth: 1, direction: "both", edge_type: nil, limit: 1000) # Ultipa GQL uses the ISO quantified-path form `-[]->{1,N}`, NOT Cypher's # `-[*1..N]->` (which is a parse error on gqldb). edge = edge_type ? ":`#{edge_type}`" : "" quant = "{1,#{depth.to_i}}" pattern = case direction when "out" then "(n)-[#{edge}]->#{quant}(m)" when "in" then "(n)<-[#{edge}]-#{quant}(m)" else "(n)-[#{edge}]-#{quant}(m)" end gql = "MATCH #{pattern} WHERE id(n) = $start " \ "RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props " \ "LIMIT #{limit.to_i}" rows = run(gql, params: { "start" => start_id }, read_only: true).dicts rows.map { |row| node_from_row(row) } end |
#update_node(node_id, properties) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/tina4/drivers/ultipa_graph_driver.rb', line 91 def update_node(node_id, properties) properties ||= {} sets = properties.keys.map { |key| "n.#{key} = $p_#{key}" }.join(", ") params = {} properties.each { |key, value| params["p_#{key}"] = value } params["id"] = node_id gql = "MATCH (n) WHERE id(n) = $id SET #{sets} " \ "RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props" rows = run(gql, params: params, read_only: false).dicts node_from_row(rows[0]) end |