@@ -16,10 +16,10 @@ class Vertex(object):
16
16
def __init__ (self , _id ):
17
17
self .id = _id
18
18
self .tags = {}
19
- self .edge = None
19
+ self .edges = set ()
20
20
21
21
def set_edge (self , edge ):
22
- self .edge = edge
22
+ self .edges . add ( edge )
23
23
return self
24
24
25
25
def get_dict (self ):
@@ -30,8 +30,7 @@ def __str__(self):
30
30
31
31
class Graph :
32
32
"""
33
- https://www.w3.org/TR/WD-rdf-syntax-971002/
34
- https://github.com/cayleygraph/cayley/blob/master/docs/GizmoAPI.md
33
+ Creates a graph object.
35
34
"""
36
35
37
36
def __init__ (self , graph_name , cog_home = "cog_home" , cog_path_prefix = None ):
@@ -78,7 +77,7 @@ def load_triples(self, graph_data_path, graph_name=None):
78
77
79
78
def load_csv (self , csv_path , id_column_name , graph_name = None ):
80
79
"""
81
- Loads CSV to a graph. One column must be designated as ID column
80
+ Loads CSV to a graph. One column must be designated as ID column.
82
81
:param csv_path:
83
82
:param id_column_name:
84
83
:param graph_name:
@@ -101,7 +100,6 @@ def put(self, vertex1, predicate, vertex2):
101
100
return self
102
101
103
102
def v (self , vertex = None ):
104
- #TODO: need to check if node exists
105
103
if vertex is not None :
106
104
self .last_visited_vertices = [Vertex (vertex )]
107
105
else :
@@ -113,14 +111,14 @@ def v(self, vertex=None):
113
111
114
112
def out (self , predicates = None ):
115
113
'''
116
- List of string predicates
117
- :param predicates:
114
+ Traverse forward through edges.
115
+ :param predicates: A string or a List of strings.
118
116
:return:
119
117
'''
120
118
if predicates is not None :
121
119
if not isinstance (predicates , list ):
122
120
predicates = [predicates ]
123
- predicates = map (hash_predicate , predicates )
121
+ predicates = list ( map (hash_predicate , predicates ) )
124
122
else :
125
123
predicates = self .all_predicates
126
124
@@ -129,21 +127,94 @@ def out(self, predicates=None):
129
127
return self
130
128
131
129
def inc (self , predicates = None ):
130
+ '''
131
+ Traverse backward through edges.
132
+ :param predicates:
133
+ :return:
134
+ '''
132
135
if predicates is not None :
133
136
if not isinstance (predicates , list ):
134
137
predicates = [predicates ]
135
- predicates = map (hash_predicate , predicates )
138
+ predicates = list ( map (hash_predicate , predicates ) )
136
139
else :
137
140
predicates = self .all_predicates
138
141
139
142
self .__hop ("in" , predicates )
140
143
return self
141
144
142
- def has (self , predicate , object ):
143
- pass
145
+ def __adjacent_vertices (self , vertex , predicates , direction = 'out' ):
146
+ self .cog .use_namespace (self .graph_name )
147
+ adjacent_vertices = []
148
+ for predicate in predicates :
149
+ if direction == 'out' :
150
+ out_record = self .cog .use_table (predicate ).get (out_nodes (vertex .id ))
151
+ if not out_record .is_empty ():
152
+ for v_adj in out_record .value :
153
+ adjacent_vertices .append (Vertex (v_adj ).set_edge (predicate ))
154
+ elif direction == 'in' :
155
+ in_record = self .cog .use_table (predicate ).get (in_nodes (vertex .id ))
156
+ if not in_record .is_empty ():
157
+ for v_adj in in_record .value :
158
+ adjacent_vertices .append (Vertex (v_adj ).set_edge (predicate ))
159
+
160
+ return adjacent_vertices
161
+
162
+ def has (self , predicates , vertex ):
163
+ """
164
+ Filters all outgoing edges from a vertex that matches a list of predicates.
165
+ :param predicates:
166
+ :param vertex:
167
+ :return:
168
+ """
169
+
170
+ if predicates is not None :
171
+ if not isinstance (predicates , list ):
172
+ predicates = [predicates ]
173
+ predicates = list (map (hash_predicate , predicates ))
174
+
175
+ has_vertices = []
176
+ for lv in self .last_visited_vertices :
177
+ adj_vertices = self .__adjacent_vertices (lv , predicates )
178
+ # print(lv.id + " -> " + str([x.id for x in adj_vertices]))
179
+ for av in adj_vertices :
180
+ if av .id == vertex :
181
+ has_vertices .append (lv )
182
+
183
+ self .last_visited_vertices = has_vertices
184
+ return self
185
+
186
+ def hasr (self , predicates , vertex ):
187
+ """
188
+ 'Has' in reverse. Filters all incoming edges from a vertex that matches a list of predicates.
189
+ :param predicates:
190
+ :param vertex:
191
+ :return:
192
+ """
193
+
194
+ if predicates is not None :
195
+ if not isinstance (predicates , list ):
196
+ predicates = [predicates ]
197
+ predicates = list (map (hash_predicate , predicates ))
198
+
199
+ has_vertices = []
200
+ for lv in self .last_visited_vertices :
201
+ adj_vertices = self .__adjacent_vertices (lv , predicates , 'in' )
202
+ # print(lv.id + " -> " + str([x.id for x in adj_vertices]))
203
+ for av in adj_vertices :
204
+ if av .id == vertex :
205
+ has_vertices .append (lv )
206
+
207
+ self .last_visited_vertices = has_vertices
208
+ return self
144
209
145
210
146
211
def scan (self , limit = 10 , scan_type = 'v' ):
212
+ '''
213
+ Scans vertices or edges in a graph.
214
+ :param limit:
215
+ :param scan_type:
216
+ :return:
217
+ '''
147
218
assert type (scan_type ) is str , "Scan type must be either 'v' for vertices or 'e' for edges."
148
219
if scan_type == 'e' :
149
220
self .cog .use_namespace (self .graph_name ).use_table (self .config .GRAPH_EDGE_SET_TABLE_NAME )
@@ -183,8 +254,7 @@ def __hop(self, direction, predicates=None, tag=NOTAG):
183
254
184
255
def tag (self , tag_name ):
185
256
'''
186
- Saves nodes with a tag name and returned in the result set.
187
- Primarily used to capture nodes while navigating the graph.
257
+ Saves vertices with a tag name. Used to capture vertices while traversing a graph.
188
258
:param tag_name:
189
259
:return:
190
260
'''
@@ -195,15 +265,18 @@ def tag(self, tag_name):
195
265
def count (self ):
196
266
return len (self .last_visited_vertices )
197
267
198
- def all (self ):
268
+ def all (self , options = None ):
199
269
"""
200
- returns all the nodes in the result .
270
+ Returns all the vertices that are resultant of the graph query. Options 'e' would include the edges that were traversed .
201
271
https://github.com/cayleygraph/cayley/blob/master/docs/GizmoAPI.md
202
272
:return:
203
273
"""
204
274
result = []
275
+ show_edge = True if options is not None and 'e' in options else False
205
276
for v in self .last_visited_vertices :
206
- item = {"id" :v .id }
277
+ item = {"id" : v .id }
278
+ if show_edge and v .edges :
279
+ item ['edges' ] = [self .cog .use_namespace (self .graph_name ).use_table (self .config .GRAPH_EDGE_SET_TABLE_NAME ).get (edge ).value for edge in v .edges ]
207
280
# item['edge'] = self.cog.use_namespace(self.graph_name).use_table(self.config.GRAPH_EDGE_SET_TABLE_NAME).get(item['edge']).value
208
281
item .update (v .tags )
209
282
@@ -213,7 +286,7 @@ def all(self):
213
286
214
287
def view (self , view_name , js_src = "https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js" ):
215
288
"""
216
- Returns html view of the graph
289
+ Returns html view of the resulting graph from a query.
217
290
:return:
218
291
"""
219
292
assert view_name is not None , "a view name is required to create a view, it can be any string."
0 commit comments