def fetch_properties( self, prop_name: str, prop_type: Callable[["Property"], "Property"]) -> List["Property"]: query = f""" {{ res(func: eq(node_key, "{self.node_key}")) @cascade {{ uid, node_key, node_type: dgraph.type, {prop_name} }} }} """ txn = self.dgraph_client.txn(read_only=True) try: res = json.loads(txn.query(query).json) finally: txn.discard() raw_props = res["res"] if not raw_props: return [] props = [prop_type(p[prop_name]) for p in raw_props] props = [unescape_dgraph_str(prop) for prop in props] return props
def fetch_property( self, prop_name: str, prop_type: Callable[["Property"], "Property"] ) -> Optional[Union[str, int]]: node_key_prop = "" if prop_name != "node_key": node_key_prop = "node_key" query = f""" {{ res(func: eq(node_key, "{self.node_key}"), first: 1) @cascade {{ uid, node_type: dgraph.type, {node_key_prop}, {prop_name} }} }} """ txn = self.dgraph_client.txn(read_only=True) try: res = json.loads(txn.query(query).json) finally: txn.discard() raw_prop = res["res"] if not raw_prop: return None if isinstance(raw_prop, list): raw_prop = raw_prop[0] if raw_prop.get(prop_name) is None: return None prop = prop_type(raw_prop[prop_name]) if isinstance(prop, str): return unescape_dgraph_str(prop) return prop
def from_dict(cls: Type["NV"], dgraph_client: DgraphClient, d: Dict[str, Any]) -> "NV": properties = {} node_type = d.get("node_type") or d.get("dgraph.type") if node_type: if isinstance(node_type, list): if len(node_type) > 1: # TODO: This is a hack, workaround for a preexisting bug where some nodes are labeled as Risk node_type = [nt for nt in node_type if nt != "Risk"] if len(node_type) > 1: print( f"WARN: Node has multiple types: {node_type}, narrowing to: {node_type[0]}" ) node_type = node_type[0] properties["node_type"] = node_type else: print( f"WARN: Node is missing type: {d.get('node_key', d.get('uid'))}" ) for prop, into in cls._get_property_types().items(): val = d.get(prop) if val or val == 0: if into == str: val = unescape_dgraph_str(str(val)) elif into == int: val = int(val) properties[prop] = val edges = {} # type: Dict[str, Union[Viewable, List[Viewable]]] for edge_tuple in cls.get_edge_types().items(): edge_name = edge_tuple[0] # type: str forward_name = None # type: Optional[str] if isinstance(edge_tuple[1], tuple): ty = edge_tuple[1][0] # type: EdgeViewT forward_name = edge_tuple[1][1] else: ty = edge_tuple[1] raw_edge = d.get(edge_name, None) if not raw_edge: continue if isinstance(ty, List): ty = ty[0] if d.get(edge_name, None): f_edge = d[edge_name] if isinstance(f_edge, list): _edges = [ ty.from_dict(dgraph_client, f) for f in f_edge ] elif isinstance(f_edge, dict): _edges = [ty.from_dict(dgraph_client, f_edge)] else: raise TypeError( f"Edge {edge_name} must be list or dict") if forward_name: edges[forward_name] = _edges else: edges[edge_name] = _edges else: if isinstance(raw_edge, list): edge = ty.from_dict(dgraph_client, raw_edge[0]) elif isinstance(raw_edge, dict): edge = ty.from_dict(dgraph_client, raw_edge) else: raise TypeError(f"Edge {edge_name} must be list or dict") if forward_name: edges[forward_name] = edge else: edges[edge_name] = edge cleaned_edges = {} # type: Dict[str, Union[Viewable, List[Viewable]]] for _edge in edges.items(): edge_name = _edge[0] cleaned_edge = _edge[1] # type: Union[Viewable, List[Viewable]] if edge_name[0] == "~": edge_name = edge_name[1:] cleaned_edges[edge_name] = cleaned_edge return cls( dgraph_client=dgraph_client, node_key=d["node_key"], uid=d["uid"], **properties, **cleaned_edges, )