neo4j :: Neo4jClient
Neo4jClient
is needed to communicate through the REST APIvar client = new Neo4jClient("http://neo4j:7474")
assert client.is_ok
neo4j :: Neo4jClient :: base_url=
Neo4j REST services baseurlneo4j :: Neo4jClient :: defaultinit
neo4j :: Neo4jClient :: delete_node
Remove the entity from baseneo4j :: Neo4jClient :: nodes_with_label
Retrieve all nodes with specifiedlbl
neo4j :: Neo4jClient :: nodes_with_labels
Retrieve nodes belonging to all the specifiedlabels
.
neo4j :: Neo4jClient :: post
POSTparams
to url
neo4j :: Neo4jClient :: put
PUTparams
at url
neo4j :: Neo4jClient :: service_root
neo4j $ Neo4jClient :: SELF
Type of this instance, automatically specialized in every classneo4j :: Neo4jClient :: base_url=
Neo4j REST services baseurlcore :: Object :: class_factory
Implementation used byget_class
to create the specific class.
core :: Object :: defaultinit
neo4j :: Neo4jClient :: defaultinit
neo4j :: Neo4jClient :: delete_node
Remove the entity from basecore :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
neo4j :: Neo4jClient :: nodes_with_label
Retrieve all nodes with specifiedlbl
neo4j :: Neo4jClient :: nodes_with_labels
Retrieve nodes belonging to all the specifiedlabels
.
core :: Object :: output_class_name
Display class name on stdout (debug only).neo4j :: Neo4jClient :: post
POSTparams
to url
neo4j :: Neo4jClient :: put
PUTparams
at url
neo4j :: Neo4jClient :: service_root
# `Neo4jClient` is needed to communicate through the REST API
#
# var client = new Neo4jClient("http://neo4j:7474")
# assert client.is_ok
class Neo4jClient
# Neo4j REST services baseurl
var base_url: String
# REST service to get node data
private var node_url: String
# REST service to batch
private var batch_url: String
# REST service to send cypher requests
private var cypher_url: String
init(base_url: String) do
self.base_url = base_url
var root = service_root
assert root isa JsonObject else
sys.stderr.write "Neo4jClientError: cannot connect to server at <{base_url}>.\n"
end
self.node_url = root["node"].to_s
self.batch_url = root["batch"].to_s
self.cypher_url = root["cypher"].to_s
end
fun service_root: Serializable do return get(base_url / "db/data")
# Is the connection with the Neo4j server ok?
fun is_ok: Bool do return service_root isa JsonObject
# Empty the graph
fun clear_graph do
cypher(new CypherQuery.from_string("MATCH (n) OPTIONAL MATCH n-[r]-() DELETE r, n"))
end
# Last errors
var errors = new Array[String]
# Nodes view stored locally
private var local_nodes = new HashMap[String, nullable NeoNode]
# Save the node in base
#
# var client = new Neo4jClient("http://neo4j:7474")
#
# # Create a node
# var andres = new NeoNode
# andres["name"] = "Andres"
# client.save_node(andres)
# assert andres.is_linked
#
# Once linked, nodes cannot be created twice:
#
# var oldurl = andres.url
# client.save_node(andres) # do nothing
# assert andres.url == oldurl
fun save_node(node: NeoNode): Bool do
if node.is_linked then return true
node.neo = self
var batch = new NeoBatch(self)
batch.save_node(node)
# batch.create_edges(node.out_edges)
var errors = batch.execute
if not errors.is_empty then
errors.add_all errors
return false
end
local_nodes[node.url.to_s] = node
return true
end
# Load a node from base
# Data, labels and edges will be loaded lazily.
fun load_node(url: String): NeoNode do
if local_nodes.has_key(url) then
var node = local_nodes[url]
if node != null then return node
end
var node = new NeoNode.from_neo(self, url)
local_nodes[url] = node
return node
end
# Remove the entity from base
fun delete_node(node: NeoNode): Bool do
if not node.is_linked then return false
var url = node.url.to_s
delete(url)
local_nodes[url] = null
node.url = null
return true
end
# Edges view stored locally
private var local_edges = new HashMap[String, nullable NeoEdge]
# Save the edge in base
# From and to nodes will be created.
#
# var client = new Neo4jClient("http://neo4j:7474")
#
# var andres = new NeoNode
# var kate = new NeoNode
# var edge = new NeoEdge(andres, "LOVES", kate)
# client.save_edge(edge)
# assert andres.is_linked
# assert kate.is_linked
# assert edge.is_linked
fun save_edge(edge: NeoEdge): Bool do
if edge.is_linked then return true
edge.neo = self
edge.from.out_edges.add edge
edge.to.in_edges.add edge
var batch = new NeoBatch(self)
batch.save_edge(edge)
var errors = batch.execute
if not errors.is_empty then
errors.add_all errors
return false
end
local_edges[edge.url.to_s] = edge
return true
end
# Load a edge from base
# Data will be loaded lazily.
fun load_edge(url: String): NeoEdge do
if local_edges.has_key(url) then
var node = local_edges[url]
if node != null then return node
end
var edge = new NeoEdge.from_neo(self, url)
local_edges[url] = edge
return edge
end
# Remove the edge from base
fun delete_edge(edge: NeoEdge): Bool do
if not edge.is_linked then return false
var url = edge.url.to_s
delete(url)
local_edges[url] = null
edge.url = null
return true
end
# Retrieve all nodes with specified `lbl`
#
# var client = new Neo4jClient("http://neo4j:7474")
#
# var andres = new NeoNode
# andres.labels.add_all(["Human", "Male"])
# client.save_node(andres)
# var kate = new NeoNode
# kate.labels.add_all(["Human", "Female"])
# client.save_node(kate)
#
# var nodes = client.nodes_with_label("Human")
# assert nodes.has(andres)
# assert nodes.has(kate)
fun nodes_with_label(lbl: String): Array[NeoNode] do
var res = get(base_url / "db/data/label/{lbl.to_percent_encoding}/nodes")
var nodes = new Array[NeoNode]
for json in res.as(JsonArray) do
var obj = json.as(JsonObject)
var node = load_node(obj["self"].to_s)
node.internal_properties = obj["data"].as(JsonObject)
nodes.add node
end
return nodes
end
# Retrieve nodes belonging to all the specified `labels`.
#
# var client = new Neo4jClient("http://neo4j:7474")
#
# var andres = new NeoNode
# andres.labels.add_all(["Human", "Male"])
# client.save_node(andres)
# var kate = new NeoNode
# kate.labels.add_all(["Human", "Female"])
# client.save_node(kate)
#
# var nodes = client.nodes_with_labels(["Human", "Male"])
# assert nodes.has(andres)
# assert not nodes.has(kate)
fun nodes_with_labels(labels: Array[String]): Array[NeoNode] do
assert not labels.is_empty
# Build the query.
var buffer = new Buffer
buffer.append "match (n) where \{label_0\} in labels(n)"
for i in [1..labels.length[ do
buffer.append " and \{label_{i}\} in labels(n)"
end
buffer.append " return n"
var query = new CypherQuery.from_string(buffer.write_to_string)
for i in [0..labels.length[ do
query.params["label_{i}"] = labels[i]
end
# Retrieve the answer.
var res = cypher(query)
var nodes = new Array[NeoNode]
for json in res.as(JsonObject)["data"].as(JsonArray) do
var obj = json.as(JsonArray).first.as(JsonObject)
var node = load_node(obj["self"].to_s)
node.internal_properties = obj["data"].as(JsonObject)
nodes.add node
end
return nodes
end
# Perform a `CypherQuery`
# see: CypherQuery
fun cypher(query: CypherQuery): Serializable do
return post("{cypher_url}", query.to_rest)
end
# GET JSON data from `url`
fun get(url: String): Serializable do
var request = new JsonGET(url)
var response = request.execute
return parse_response(response)
end
# POST `params` to `url`
fun post(url: String, params: Serializable): Serializable do
var request = new JsonPOST(url)
request.json_data = params
var response = request.execute
return parse_response(response)
end
# PUT `params` at `url`
fun put(url: String, params: Serializable): Serializable do
var request = new JsonPUT(url)
request.json_data = params
var response = request.execute
return parse_response(response)
end
# DELETE `url`
fun delete(url: String): Serializable do
var request = new JsonDELETE(url)
var response = request.execute
return parse_response(response)
end
# Parse the cURL `response` as a JSON string
private fun parse_response(response: CurlResponse): Serializable do
if response isa CurlResponseSuccess then
var str = response.body_str
if str.is_empty then return new JsonObject
var res = str.parse_json
if res isa JsonParseError then
var e = new NeoError(res.to_s, "JsonParseError")
e.cause = res
return e
end
if res == null then
# empty response wrap it in empty object
return new JsonObject
else if res isa JsonObject and res.has_key("exception") then
var error = "Neo4jError::{res["exception"] or else "null"}"
var msg = ""
if res.has_key("message") then
msg = res["message"].to_s
end
return new NeoError(msg, error)
else
return res
end
else if response isa CurlResponseFailed then
return new NeoError("{response.error_msg} ({response.error_code})", "CurlError")
else
return new NeoError("Unexpected response \"{response}\".", "CurlError")
end
end
end
lib/neo4j/neo4j.nit:63,1--343,3