@@ -23,7 +23,8 @@ class Entities(Subscriptable):
2323 @classmethod
2424 def retrieve (cls ,
2525 db : Connector ,
26- spec : Query
26+ spec : Query ,
27+ with_adjacent : Dict [str , Query ] = None
2728 ) -> List [Entities ]:
2829 """
2930 Using the Entities.retrieve method, is a simpple layer, with typical native queries converted
@@ -39,19 +40,41 @@ def retrieve(cls,
3940 Returns:
4041 List[Entities]: _description_
4142 """
43+
44+ # Since adjacent items are usually a way to filter the results,
45+ # the native query is constructed in the reverse order, with
46+ # first filtering out the relevant itmes based on adjacent items.
47+ fs = None
48+ count = 0
49+ if with_adjacent :
50+ for k , v in with_adjacent .items ():
51+ if fs is None :
52+ fs = v
53+ else :
54+ fs = fs .connected_to (v )
55+ count += 1
56+ # Eventually, connect the specification of Images to the specification of the adjacent items.
57+ fs = fs .connected_to (spec )
58+ else :
59+ fs = spec
60+
61+ spec = fs
62+
4263 cls .known_entities = load_entities_registry (
4364 custom_entities = spec .command_properties (prop = "with_class" ))
4465 cls .db = db
45- if cls .db_object != "Entity" :
46- spec .with_class = cls .db_object
4766
4867 query = spec .query ()
4968 print (f"query={ query } " )
5069 res , r , b = execute_batch (query , [], db )
5170 if res > 0 :
5271 print (f"resp={ r } " )
5372 results = []
54- for wc , req , resp in zip (spec .command_properties (prop = "with_class" ), spec .command_properties (prop = "find_command" ), r ):
73+ for wc , req , blobs , resp in zip (
74+ spec .command_properties (prop = "with_class" ),
75+ spec .command_properties (prop = "find_command" ),
76+ spec .command_properties (prop = "blobs" ),
77+ r ):
5578 subresponse = resp [req ]['entities' ]
5679 if not isinstance (subresponse , list ):
5780 flattened = []
@@ -61,13 +84,39 @@ def retrieve(cls,
6184 try :
6285 entities = cls .known_entities [wc ](
6386 db = db , response = subresponse , type = wc )
87+ entities .blobs = blobs
88+ if wc [0 ] == "_" :
89+ entities .find_command = f"Find{ wc [1 :]} "
6490 results .append (entities )
6591 except Exception as e :
6692 print (e )
6793 print (cls .known_entities )
6894 raise e
95+
96+ cls .__postprocess__ (entities = results [- 1 ], with_adjacent = with_adjacent )
6997 return results
7098
99+ # This needs to be defined so that the application can access the adjacent items,
100+ # with every item of this iterable.
101+ @classmethod
102+ def __decorator (cls , index , adjacent ):
103+ item = {}
104+ for k , v in adjacent .items ():
105+ item [k ] = v [index ]
106+ return item
107+
108+ @classmethod
109+ def __postprocess__ (cls , entities : Entities , with_adjacent : object = None ):
110+ adjacent = {}
111+ if with_adjacent :
112+ for k , v in with_adjacent .items ():
113+ adjacent [k ] = entities .get_connected_entities (
114+ etype = v .with_class ,
115+ constraints = v .constraints )
116+
117+ entities .decorator = cls .__decorator
118+ entities .adjacent = adjacent
119+
71120 def __init__ (self , db : Connector = None , response : dict = None , type : str = None ) -> None :
72121 super ().__init__ ()
73122 self .db = db
@@ -99,7 +148,7 @@ def __sub__(self, other: Entities) -> Entities:
99148 def sort (self , key ) -> Entities :
100149 return Entities (response = sorted (self .response , key = key ), type = self .type )
101150
102- def inspect (self ) -> pd .DataFrame :
151+ def inspect (self , ** kwargs ) -> pd .DataFrame :
103152 return pd .json_normalize ([item for item in self ])
104153
105154 def update_properties (self , extra_properties : List [dict ]) -> bool :
@@ -129,6 +178,7 @@ def get_connected_entities(self, etype: Union[ObjectType, str], constraints: Co
129178 List[Entities]: _description_
130179 """
131180 result = []
181+ entity_class = etype .value if isinstance (etype , ObjectType ) else etype
132182 for entity in self :
133183 query = [
134184 {
@@ -144,7 +194,7 @@ def get_connected_entities(self, etype: Union[ObjectType, str], constraints: Co
144194 "is_connected_to" : {
145195 "ref" : 1
146196 },
147- "with_class" : type . value ,
197+ "with_class" : entity_class ,
148198 "constraints" : constraints .constraints ,
149199 "results" : {
150200 "all_properties" : True
@@ -153,10 +203,34 @@ def get_connected_entities(self, etype: Union[ObjectType, str], constraints: Co
153203 }
154204 ]
155205 res , r , b = execute_batch (query , [], self .db )
156- result .append (self .known_entities [type .value ](
157- db = self .db , response = r [1 ]["FindEntity" ]["entities" ], type = type .value ))
206+ cl = Entities
207+ if entity_class in self .known_entities :
208+ cl = self .known_entities [entity_class ]
209+ result .append (cl (
210+ db = self .db , response = r [1 ]["FindEntity" ]["entities" ], type = entity_class ))
158211 return result
159212
213+ def get_blob (self , entity ) -> Any :
214+ """
215+ Helper to get blobs for FindImage, FindVideo and FindBlob commands.
216+ """
217+ query = [
218+ {
219+ self .find_command : {
220+ "constraints" : {
221+ "_uniqueid" : ["==" , entity ["_uniqueid" ]]
222+ },
223+ "blobs" : True ,
224+ "uniqueids" : True ,
225+ "results" : {
226+ "count" : True
227+ }
228+ }
229+ }
230+ ]
231+ res , r , b = execute_batch (query , [], self .db )
232+ return b [0 ]
233+
160234
161235def load_entities_registry (custom_entities : List [str ] = None ) -> dict :
162236 from aperturedb .Polygons import Polygons
0 commit comments