end
# Retrieve all nodes with specified `lbl`
+ #
+ # var client = new Neo4jClient("http://localhost: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}/nodes")
var nodes = new Array[NeoNode]
- var batch = new NeoBatch(self)
- for obj in res.as(JsonArray) do
- var node = new NeoNode.from_json(self, obj.as(JsonObject))
- batch.load_node(node)
+ 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://localhost: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
+ var res = cypher(new CypherQuery.from_string("MATCH (n:{labels.join(":")}) RETURN n"))
+ 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
- batch.execute
return nodes
end
# For more details, see: http://docs.neo4j.org/chunked/milestone/rest-api-cypher.html
class CypherQuery
# Query string to perform
- private var query: String
+ private var query: String = ""
# `params` to embed in the query like in prepared statements
var params = new JsonObject
- init do
- self.query = ""
- end
+ init do end
# init the query from a query string
init from_string(query: String) do
# assert node["name"] == "Andres" # loaded lazily from base
abstract class NeoEntity
# Neo4j client connector
- private var neo: Neo4jClient
+ private var neo: Neo4jClient is noinit
# Entity unique URL in Neo4j REST API
- var url: nullable String
+ var url: nullable String = null
# Temp id used in batch mode to update the entity
private var batch_id: nullable Int = null
fun from: NeoNode do return internal_from or else load_from
private fun load_from: NeoNode do
- var node = new NeoNode.from_neo(neo, internal_from_url.to_s)
+ var node = neo.load_node(internal_from_url.to_s)
internal_from = node
return node
end
fun to: NeoNode do return internal_to or else load_to
private fun load_to: NeoNode do
- var node = new NeoNode.from_neo(neo, internal_to_url.to_s)
+ var node = neo.load_node(internal_to_url.to_s)
internal_to = node
return node
end
# Load a node in batch mode also load labels, data and edges
fun load_node(node: NeoNode) do
- load_node_data(node)
- load_node_labels(node)
- load_node_out_edges(node)
- end
-
- # Load data into node
- private fun load_node_data(node: NeoNode) do
var job = new_job(node)
job.action = load_node_data_action
job.method = "GET"
else
job.to = "\{{node.batch_id.to_s}\}"
end
- end
-
- # Load labels into node
- private fun load_node_labels(node: NeoNode) do
- var job = new_job(node)
+ job = new_job(node)
job.action = load_node_labels_action
job.method = "GET"
if node.id != null then
end
end
- # Load out edges into node
- private fun load_node_out_edges(node: NeoNode) do
+ # Load in and out edges into node
+ fun load_node_edges(node: NeoNode) do
var job = new_job(node)
+ job.action = load_node_in_edges_action
+ job.method = "GET"
+ if node.id != null then
+ job.to = "/node/{node.id.to_s}/relationships/in"
+ else
+ job.to = "\{{node.batch_id.to_s}\}/relationships/in"
+ end
+ job = new_job(node)
job.action = load_node_out_edges_action
job.method = "GET"
if node.id != null then
end
end
+ # Create a `NeoNode` or a `NeoEdge` in batch mode.
+ fun save_entity(nentity: NeoEntity) do
+ if nentity isa NeoNode then
+ save_node(nentity)
+ else if nentity isa NeoEdge then
+ save_edge(nentity)
+ else abort
+ end
+
# Create a node in batch mode also create labels and edges
fun save_node(node: NeoNode) do
if node.id != null or node.batch_id != null then return
job.to = "\{{node.batch_id.to_s}\}/labels"
job.body = new JsonArray.from(node.labels)
# add edges
- save_edges(node.out_edges)
+ #save_edges(node.out_edges)
end
# Create multiple nodes
var labels = new Array[String]
for l in res["body"].as(JsonArray) do labels.add l.to_s
node.internal_labels = labels
+ else if job.action == load_node_in_edges_action then
+ var node = job.entity.as(NeoNode)
+ var edges = res["body"].as(JsonArray)
+ node.internal_in_edges = new List[NeoEdge]
+ for edge in edges do
+ node.internal_in_edges.add client.load_edge(edge.as(JsonObject)["self"].to_s)
+ end
else if job.action == load_node_out_edges_action then
var node = job.entity.as(NeoNode)
var edges = res["body"].as(JsonArray)
node.internal_out_edges = new List[NeoEdge]
for edge in edges do
- node.internal_out_edges.add new NeoEdge.from_json(client, edge.as(JsonObject))
+ node.internal_out_edges.add client.load_edge(edge.as(JsonObject)["self"].to_s)
end
end
end
private fun create_edge_action: Int do return 2
private fun load_node_data_action: Int do return 3
private fun load_node_labels_action: Int do return 4
- private fun load_node_out_edges_action: Int do return 5
+ private fun load_node_in_edges_action: Int do return 5
+ private fun load_node_out_edges_action: Int do return 6
end
# A job that can be executed in a `NeoBatch`