Skip to content

Commit

Permalink
Updated geoff.py to support relationship index entries
Browse files Browse the repository at this point in the history
  • Loading branch information
technige committed Sep 18, 2011
1 parent 3cf557b commit 29ebbce
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 23 deletions.
2 changes: 1 addition & 1 deletion examples/example1.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# Allow the import path to access neo4j modules
import sys
sys.path.append("../src")
sys.path.append("../src")

from py2neo import neo4j

Expand Down
18 changes: 18 additions & 0 deletions examples/geoff/load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env python

"""
Script to load sample GEOFF file into database
"""

from py2neo import neo4j

# Attach to the graph db instance
gdb = neo4j.GraphDatabaseService("http://localhost:7474/db/data")

# Obtain a link to the reference node of the db
ref_node = gdb.get_reference_node()

# Load the royal family into the database
handle = geoff.load(file("royals.geoff"), gdb)
print "New data available from node %s" % (handle)

18 changes: 14 additions & 4 deletions examples/royals.geoff → examples/geoff/royals.geoff
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# This data represents a portion of the British Royal Family

# First, we define the nodes (in this case, people)
(Liz) {"name": "Elizabeth", "title": "Queen of the Commonwealth Realms", "birth.date": "1926-04-21"}
(Phil) {"name": "Philip", "title": "Duke of Edinburgh", "birth.date": "1921-06-21"}
(Chaz) {"name": "Charles", "title": "Prince of Wales", "birth.date": "1948-11-14"}
Expand All @@ -7,15 +9,19 @@
(Wills) {"name": "William", "title": "Duke of Cambridge", "birth.date": "1982-06-21"}
(Harry) {"name": "Henry", "birth.date": "1984-09-15"}
(Kate) {"name": "Catherine", "title": "Duchess of Cambridge", "birth.date": "1982-01-09"}
(Liz)-[:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}

# Next come the realtionships between the people
(Liz)-[1947:MARRIED]->(Phil) {"marriage.place": "Westminster Abbey", "marriage.date": "1947-11-20"}
(Liz)-[:MOTHER_OF]->(Chaz)
(Phil)-[:FATHER_OF]->(Chaz)
(Di)-[:MARRIED]->(Chaz) {"marriage.place": "St Paul's Cathedral", "marriage.date": "1981-07-29", "divorce.date": "1996-08-28"}
(Di)-[1981:MARRIED]->(Chaz) {"marriage.place": "St Paul's Cathedral", "marriage.date": "1981-07-29", "divorce.date": "1996-08-28"}
(Di)-[:MOTHER_OF]->(Wills)
(Chaz)-[:FATHER_OF]->(Wills)
(Di)-[:MOTHER_OF]->(Harry)
(Cam)-[:MARRIED]->(Chaz) {"marriage.place": "Windsor Guildhall", "marriage.date": "2005-04-09"}
(Kate)-[:MARRIED]->(Wills) {"marriage.place": "Westminster Abbey", "marriage.date": "2011-04-29"}
(Cam)-[2005:MARRIED]->(Chaz) {"marriage.place": "Windsor Guildhall", "marriage.date": "2005-04-09"}
(Kate)-[2011:MARRIED]->(Wills) {"marriage.place": "Westminster Abbey", "marriage.date": "2011-04-29"}

# And finally the index entries for the nodes and relationships
{People}->(Liz) {"name": "Elizabeth"}
{People}->(Phil) {"name": "Philip"}
{People}->(Chaz) {"name": "Charles"}
Expand All @@ -24,4 +30,8 @@
{People}->(Wills) {"name": "William"}
{People}->(Harry) {"name": "Henry"}
{People}->(Kate) {"name": "Catherine"}
{Weddings}->[1947] {"year": 1947}
{Weddings}->[1981] {"year": 1981}
{Weddings}->[2005] {"year": 2005}
{Weddings}->[2011] {"year": 2011}

58 changes: 44 additions & 14 deletions src/py2neo/geoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ def load(self):
first_node_id = None
nodes = {}
rels = []
index_entries = {}
named_rels = {}
node_index_entries = {}
rel_index_entries = {}
line_no = 0
for line in self.file:
# increment line no and trim whitespace from current line
Expand All @@ -101,12 +103,15 @@ def load(self):
)
if start_node not in nodes or end_node not in nodes:
raise ValueError("Invalid node reference on line %d: %s" % (line_no, repr(m.group(1))))
rels.append({
rel = {
'start_node': start_node,
'end_node': end_node,
'type': type,
'data': json.loads(m.group(8) or 'null')
})
}
if len(name or "") > 0:
named_rels[name] = len(rels)
rels.append(rel)
continue
# secondly, try as a node descriptor
if m:
Expand All @@ -116,20 +121,35 @@ def load(self):
nodes[node_id] = json.loads(m.group(8) or 'null')
first_node_id = first_node_id or node_id
continue
# neither of those, so try as an index entry descriptor
# neither of those, so try as a node index entry descriptor
m = self.NODE_INDEX_ENTRY_PATTERN.match(line)
if m:
(index, node) = (
unicode(m.group(2)),
unicode(m.group(3))
)
data = json.loads(m.group(5) or 'null')
if index not in index_entries:
index_entries[index] = {}
if node not in index_entries[index]:
index_entries[index][node] = {}
if index not in node_index_entries:
node_index_entries[index] = {}
if node not in node_index_entries[index]:
node_index_entries[index][node] = {}
if data:
index_entries[index][node].update(data)
node_index_entries[index][node].update(data)
continue
# or as a relationship index entry descriptor
m = self.RELATIONSHIP_INDEX_ENTRY_PATTERN.match(line)
if m:
(index, rel) = (
unicode(m.group(2)),
unicode(m.group(3))
)
data = json.loads(m.group(5) or 'null')
if index not in rel_index_entries:
rel_index_entries[index] = {}
if rel not in rel_index_entries[index]:
rel_index_entries[index][rel] = {}
if data:
rel_index_entries[index][rel].update(data)
continue
# no idea then... this line is invalid
raise ValueError("Cannot parse line %d: %s" % (line_no, repr(line)))
Expand All @@ -153,16 +173,26 @@ def load(self):
}
for rel in rels
])
# create index entries
if len(index_entries) > 0:
for index_key in index_entries.keys():
# create node index entries
if len(node_index_entries) > 0:
for index_key in node_index_entries.keys():
index = self.gdb.get_node_index(index_key)
index.start_batch()
for node_key in index_entries[index_key].keys():
for node_key in node_index_entries[index_key].keys():
node = nodes[node_key]
for (key, value) in index_entries[index_key][node_key].items():
for (key, value) in node_index_entries[index_key][node_key].items():
index.add(node, key, value)
index.submit_batch()
# create relationship index entries
if len(rel_index_entries) > 0:
for index_key in rel_index_entries.keys():
index = self.gdb.get_relationship_index(index_key)
index.start_batch()
for rel_key in rel_index_entries[index_key].keys():
rel = rels[named_rels[rel_key]]
for (key, value) in rel_index_entries[index_key][rel_key].items():
index.add(rel, key, value)
index.submit_batch()
return nodes[first_node_id]


Expand Down
8 changes: 4 additions & 4 deletions src/py2neo/neo4j.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,14 +915,14 @@ def add(self, entity, key, value):
if self._batch is None:
self._post(self._template_uri.format(
key=key,
value=quote(value, "")
value=quote(value, "") if isinstance(value, basestring) else value
), entity._uri)
else:
self._batch.append({
"method": "POST",
"to": self._relative_template_uri.format(
key=key,
value=quote(value, "")
value=quote(value, "") if isinstance(value, basestring) else value
),
"body": entity._uri,
"id": len(self._batch)
Expand Down Expand Up @@ -974,7 +974,7 @@ def search(self, key, value):
'method': 'GET',
'to': self._relative_template_uri.format(
key=key,
value=quote(value[i], "")
value=quote(value[i], "") if isinstance(value[i], basestring) else value[i]
),
'id': i
}
Expand All @@ -991,7 +991,7 @@ def search(self, key, value):
)
for item in self._get(self._template_uri.format(
key=key,
value=quote(value, "")
value=quote(value, "") if isinstance(value, basestring) else value
))
]

Expand Down

0 comments on commit 29ebbce

Please sign in to comment.