def test_concat_method(self): woqlObject = WOQLQuery().concat("v:Duration yo v:Duration_Cast", "x") jsonObj = { "concat": [{ "list": [ "v:Duration", { "@value": " yo ", "@type": "xsd:string" }, "v:Duration_Cast" ] }, "v:x"] } assert woqlObject.json() == jsonObj
def parent_of(child, parent, want_mother=True): ''' Query to return the mother or father (doctype) of a child (doctype). Of course, in real life, a child might be an orphan... :param child: string: woql variable or literal :param parent: string: woql variable :param want_mother: boolean: whether mother or father sought :return: Woql query result ''' local_P1 = local_variable( "v:P1") # Demarcate, because query can be used multiple times local_P2 = local_variable( "v:P2") # Demarcate, because query can be used multiple times sex = "F" if want_mother else "M" # # Terminus currently has a bug with literal values in queries. Should be able to do: # WOQLQuery().triple(local_P1, "Sex", sex) here, but instead have to use @type.. # return WOQLQuery().woql_and( parents_of(child, local_P1, local_P2), WOQLQuery().woql_or( WOQLQuery().woql_and( WOQLQuery().triple(local_P1, "Sex", literal_string(sex)), WOQLQuery().eq(local_P1, parent)), WOQLQuery().woql_and( WOQLQuery().triple(local_P2, "Sex", literal_string(sex)), WOQLQuery().eq(local_P2, parent))))
def list_people(): ''' Return a dataframe with the name of each person ''' selects = ["v:Name", "v:Sex", "v:Parent1", "v:Parent2"] # so we can return an empty dataframe if no data q = WOQLQuery().select(*selects).woql_and( WOQLQuery().triple("v:Person", "Name", "v:Name"), WOQLQuery().triple("v:Person", "Sex", "v:Sex"), WOQLQuery().triple("v:Person", "Parent1", "v:Parent1"), WOQLQuery().triple("v:Person", "Parent2", "v:Parent2")) result = wary.execute_query(q, client) return pd.DataFrame( columns=selects) if is_empty(result) else wdf.query_to_df(result)
def test_doctype_method(self): woqlObject = WOQLQuery().doctype("Station") jsonObj = { "and": [{ "add_quad": ["scm:Station", "rdf:type", "owl:Class", "db:schema"] }, { "add_quad": [ "scm:Station", "rdfs:subClassOf", "tcs:Document", "db:schema" ] }] } assert woqlObject.json() == jsonObj
def load_csvs(client, csvs): """Load the CSVs as input Parameters ========== client : a WOQLClient() connection csvs : a dict of all csvs to be input """ for key, url in csvs.items(): csv = get_csv_variables(url) wrangles = get_wrangles() inputs = WOQLQuery().woql_and(csv, *wrangles) inserts = get_inserts() answer = WOQLQuery().when(inputs, inserts) answer.execute(client)
def test_get_document_connections_method(self): woqlObject=WOQLQuery().limit(2).start(0) jsonObj={ 'limit': [ 2, { 'start': [ 0, { "and": [ {"eq": ["v:Docid", "doc:docid"]}, { "or": [ { "triple": ["doc:docid", "v:Outgoing", "v:Entid"] }, { "triple": ["v:Entid", "v:Incoming", "doc:docid" ] }, ] }, { "isa": [ "v:Entid", "v:Enttype"] }, { "sub": [ "v:Enttype", "tcs:Document"] }, { "opt": [ { "triple": ["v:Entid", "rdfs:label", "v:Label"] } ] }, { "opt": [ { "quad": ["v:Enttype", "rdfs:label", "v:Class_Label", "db:schema"] } ] } ] } ] } ] } assert woqlObject.get_document_connections("doc:docid").json() == jsonObj
def construct_type_addon(series, type_id): result = [] if type(series.subTypes) == str: for kid in series.subTypes.split(','): kid = kid.strip() if kid in list(type_id): result.append(WOQLQuery().add_quad(kid, "subClassOf", series.id, "schema")) if type(series.subTypeOf) == str: for parent in series.subTypeOf.split(','): parent = parent.strip() if parent in list(type_id): result.append(WOQLQuery().add_quad(series.id, "subClassOf", parent, "schema")) return result
def test_add_property_methof(self): woqlObject = WOQLQuery().add_property("some_property", "string") jsonObj = { 'and': [{ 'add_quad': [ 'scm:some_property', 'rdf:type', 'owl:DatatypeProperty', 'db:schema' ] }, { 'add_quad': ['scm:some_property', 'rdfs:range', 'xsd:string', 'db:schema'] }] } print(woqlObject.json()) assert woqlObject.json() == jsonObj
def get_csv_variables(url): """Extracting the data from a CSV and binding it to variables Parameters ========== client : a WOQLClient() connection url : string, the URL of the CSV """ csv = WOQLQuery().get(WOQLQuery().woql_as( "councillor_a", "v:Rep_A").woql_as("councillor_b", "v:Rep_B").woql_as("party_a", "v:Party_A").woql_as( "party_b", "v:Party_B").woql_as("distance", "v:Distance")).remote(url) return csv
def test_delete_method(self): woqlObject = WOQLQuery().delete( {'triple': ["doc:a", "scm:b", { "@language": "en", "@value": "c" }]}) jsonObj = { 'delete': [{ 'triple': ["doc:a", "scm:b", { "@language": "en", "@value": "c" }] }] } assert woqlObject.json() == jsonObj
def country_query(country): if country.fipscode: country_code = "_fips_" + country.fipscode else: country_code = "_iso_" + country.iso3166code matches_c = WOQLQuery().woql_and(WOQLQuery().idgen( "doc:Country", [country_code], "v:country_id" + country_code)) insert_c = WOQLQuery().insert("v:country_id" + country_code, "Country"). \ property("country_id", {'@type': 'xsd:string', '@value': "doc:Country" + country_code}). \ property("country_name", {'@type': 'xsd:string', '@value': country.name}).\ property("country_iso_code", {'@type': 'xsd:string', '@value': country.iso3166code}).\ property("country_fips_code", {'@type': 'xsd:string', '@value': country.fipscode}) return [matches_c, insert_c]
def create_schema(client): # # We first create an abstract class to represent ephemeral entities - things that have lifespans # schema = WOQLQuery().when(True).woql_and( WOQLQuery().doctype("EphemeralEntity").label("Ephemeral Entity"). description("An entity that has a lifespan").abstract().property( "lifespan_start", "dateTime").label("Existed From").property( "lifespan_end", "dateTime").label("Existed To"), # # This allows us to attach existence start and end times to entities, in a consistent way. # Then we create our four actual concrete classes, each as a subclass of this one: # # That gives you the meta-structure - the major relationships between airports, airlines, countries and flights - # you can then add whatever other properties you want. All the entities also have lifespan_start and lifespan_end # properties inherited from EphemeralEntity WOQLQuery().add_class("Country").label("Country").description( "A nation state").parent("EphemeralEntity").property( "country_id", "string").label("Id").property( "country_name", "string").label("Name").property( "country_iso_code", "string").label("ISO Code").property( "country_fips_code", "string").label("FIPS Code"), #primary key WOQLQuery().add_class("Airline").label("Airline").description( "An operator of airplane flights").parent( "EphemeralEntity").property("icao_code", "string").label( "ICAO Code") # primary key .property("registered_in", "Country").label("Registered In"), WOQLQuery().add_class("Airport").label("Airport").description( "An airport where flights terminate").parent( "EphemeralEntity").property( "situated_in", "Country").label("Situated In").property( "icao_code", "string").label("ICAO Code") # primary key .property("iata_code", "string").label("IATA Code").property( "name", "string").label("Name"), WOQLQuery().add_class("Flight").label("Flight").description( "A flight between airports").parent("EphemeralEntity").property( "departs", "Airport").label("Departs").property( "arrives", "Airport").label("Arrives").property( "operated_by", "Airline").label("Operated By")) try: print("[Building schema..]") with wary.suppress_Terminus_diagnostics(): schema.execute(client) except Exception as e: wary.diagnose(e)
def get_csv_variables(url): """Extracting the data from a CSV and binding it to variables Parameters ========== client : a WOQLClient() connection url : string, the URL of the CSV """ csv = WOQLQuery().get( WOQLQuery().woql_as("Start station", "v:Start_Station"). woql_as("End station", "v:End_Station"). woql_as("Start date", "v:Start_Time"). woql_as("End date", "v:End_Time"). woql_as("Duration", "v:Duration"). woql_as("Start station number", "v:Start_ID"). woql_as("End station number", "v:End_ID"). woql_as("Bike number", "v:Bike"). woql_as("Member type", "v:Member_Type") ).remote(url) return csv
def get_inserts(voyages): ''' Build a query to initialise each instance of each doctype with its corresponding properties, using the raw data previously read in from the .csv file :return: woql query for all the insertions ''' if voyages: return WOQLQuery().insert("v:Voyage_ID", "Voyage").label("v:Start").\ property("start", "v:Start_Time").\ property("end", "v:End_Time").\ property("route", "v:Route").\ property("ship", "v:Ship") else: return WOQLQuery().insert("v:Docking_ID", "Docking").label("v:Start").\ property("start", "v:Start_Time").\ property("end", "v:End_Time").\ property("berth", "v:Berth").\ property("ship", "v:Ship")
def get_inserts(): inserts = WOQLQuery().woql_and( WOQLQuery().insert("v:Journey_ID", "Journey"). label("v:Journey_Label"). description("v:Journey_Description"). property("start_time", "v:Start_Time_Cast"). property("end_time", "v:End_Time_Cast"). property("duration", "v:Duration_Cast"). property("start_station", "v:Start_Station_URL"). property("end_station", "v:End_Station_URL"). property("journey_bicycle", "v:Bike_URL"), WOQLQuery().insert("v:Start_Station_URL", "Station"). label("v:Start_Station_Label"), WOQLQuery().insert("v:End_Station_URL", "Station"). label("v:End_Station_Label"), WOQLQuery().insert("v:Bike_URL", "Bicycle"). label("v:Bike_Label") ) return inserts
def test_simple_graph_query_method(self): woqlObject=WOQLQuery().limit(2).start(0) jsonObj={ 'limit': [ 2, { 'start': [ 0, { "and": [ { "triple": [ "v:Source", "v:Edge", "v:Target"] }, { "isa": [ "v:Source", "v:Source_Class"] }, { "sub": [ "v:Source_Class", "tcs:Document"] }, { "isa": [ "v:Target", "v:Target_Class"] }, { "sub": [ "v:Target_Class", "tcs:Document"] }, { "opt": [ { "triple": ["v:Source", "rdfs:label", "v:Source_Label"] } ] }, { "opt": [ { "triple": ["v:Source", "rdfs:comment", "v:Source_Comment"] } ] }, { "opt": [ { "quad": ["v:Source_Class", "rdfs:label", "v:Source_Type", "db:schema"] } ] }, { "opt": [ { "quad": ["v:Source_Class", "rdfs:comment", "v:Source_Type_Comment", "db:schema"] } ] }, { "opt": [ { "triple": ["v:Target", "rdfs:label", "v:Target_Label"] } ] }, { "opt": [ { "triple": ["v:Target", "rdfs:comment", "v:Target_Comment"] } ] }, { "opt": [ { "quad": ["v:Target_Class", "rdfs:label", "v:Target_Type", "db:schema"] } ] }, { "opt": [ { "quad": ["v:Target_Class", "rdfs:comment", "v:Target_Type_Comment","db:schema"] } ] }, { "opt": [ { "quad": ["v:Edge", "rdfs:label", "v:Edge_Type", "db:schema"] } ] }, { "opt": [ { "quad": ["v:Edge", "rdfs:comment", "v:Edge_Type_Comment", "db:schema"] } ] } ] } ] } ] } assert woqlObject.simple_graph_query().json() == jsonObj
def create_schema(client): ''' Build the schema. For this example, it is very simple: just a doctype for a Person with various attributes :param client: TerminusDB server handle ''' schema = WOQLQuery().when(True).woql_and(WOQLQuery().doctype( "Person").label("Person").description("Somebody").property( "Name", "string").property("Sex", "string").property( "Parent1", "string").property("Parent2", "string")) try: print("[Building schema..]") with wary.suppress_Terminus_diagnostics(): schema.execute(client) except Exception as e: wary.diagnose(e)
def test_woql_or_method(self): woqlObject = WOQLQuery().woql_or(WOQLQuery().triple("a", "b", "c"), WOQLQuery().triple("1", "2", "3")) jsonObj = { 'or': [{ 'triple': ["doc:a", "scm:b", { "@language": "en", "@value": "c" }] }, { 'triple': ["doc:1", "scm:2", { "@language": "en", "@value": "3" }] }] } assert woqlObject.json() == jsonObj
def parents_of(child, parent1, parent2): ''' Query to return the parent (doctypes) of a child (doctype). Of course, in real life, a child might have a single parent, or be an orphan... :param child: string: woql variable :param parent1: string: woql variable :param parent2: string: woql variable :return: Woql query result ''' local_P1_Name = local_variable( "v:P1_Name") # Demarcate, because query can be used multiple times local_P2_Name = local_variable( "v:P2_Name") # Demarcate, because query can be used multiple times return WOQLQuery().woql_and( WOQLQuery().triple(child, "Parent1", local_P1_Name), WOQLQuery().triple(parent1, "Name", local_P1_Name), WOQLQuery().triple(child, "Parent2", local_P2_Name), WOQLQuery().triple(parent2, "Name", local_P2_Name), )
def test_again_add_class_method(self): woqlObject = WOQLQuery().add_class("NewClass").description( "A new class object.").entity() jsonObj = { "and": [{ "add_quad": ['scm:NewClass', 'rdf:type', "owl:Class", 'db:schema'] }, { "add_quad": [ 'scm:NewClass', 'rdfs:comment', { '@value': "A new class object.", '@language': 'en' }, 'db:schema' ] }, { "add_quad": ['scm:NewClass', 'rdfs:subClassOf', "tcs:Entity", 'db:schema'] }] } print(woqlObject.json()) assert woqlObject.json() == jsonObj
def get_country_code(airport, priority, id): original_name = airport.country name = original_name.replace(" ", "\\s*").replace("(", "\\(").replace(")", "\\)") def unifying(variable): return variable + str(id) property_name = getPriority(priority) # in batch , query need to be unique, so we concat with str query = WOQLQuery().woql_and( WOQLQuery().triple(unifying("v:Country"), "type", "scm:Country"), WOQLQuery().triple(unifying("v:Country"), "scm:country_name", unifying("v:country_name")), WOQLQuery().triple(unifying("v:Country"), "scm:country_id", unifying("v:country_id")), WOQLQuery().triple(unifying("v:Country"), "scm:{p}".format(p=property_name), unifying("v:{v}".format(v=property_name))), WOQLQuery().re( "(.*{re_name}.*)+".format(re_name=name), unifying("v:country_name"), [unifying("v:All"), unifying("v:Paren1")])) return [airport, query]
def list_grandchildren_of(gParent): ''' Return a dataframe with the names of the grandchildren of a grandparent. :param gParent: string: name of a grandparent :return: a dataframe with all the grandchildren ''' selects = ["v:Child_Name"] q = WOQLQuery().select(*selects).woql_and(grandchildren_of(gParent)) result = wary.execute_query(q, client) return pd.DataFrame( columns=selects) if is_empty(result) else wdf.query_to_df(result)
def list_children_of(parent): ''' Return a dataframe with the names of the children of a parent. :param parent: string: name of a parent :return: If child is None, then a dataframe with all children and their respective mothers. Otherwise, a dataframe with the mother of the given child ''' selects = ["v:Child_Name"] q = WOQLQuery().select(*selects).woql_and(children_of(parent)) result = wary.execute_query(q, client) return pd.DataFrame( columns=selects) if is_empty(result) else wdf.query_to_df(result)
def load_csv(client, url, voyages): ''' Read a .csv file and use its raw data to initialise a graph in the TerminusDB server. In the case of a local file, it should be the file path relative to the value of the TERMINUS_LOCAL environment variable set when the TerminusDB server was started... :param client: handle on the TerminusDB server :param url: string, eiher a local file name or http-style url :param voyages: boolean, whether a Voyage or Berth document set are to be created :return: None ''' csv = get_csv_variables(url, voyages) wrangles = get_wrangles(voyages) inputs = WOQLQuery().woql_and(csv, *wrangles) inserts = get_inserts(voyages) answer = WOQLQuery().when(inputs, inserts) try: print("[Loading raw data from '{}'..]".format(url)) with wary.suppress_Terminus_diagnostics(): answer.execute(client) except woqlError.APIError as e: wary.diagnose(e)
def test_insert_method(self): woqlObject = WOQLQuery().insert("v:Bike_URL", "Bicycle") woqlObjectDB = WOQLQuery().insert("v:Bike_URL", "Bicycle", "myDB") jsonObj = {"add_triple": ['v:Bike_URL', 'rdf:type', 'scm:Bicycle']} jsonObjDB = { "add_quad": ['v:Bike_URL', 'rdf:type', 'scm:Bicycle', 'db:myDB'] } assert woqlObject.json() == jsonObj assert woqlObjectDB.json() == jsonObjDB
def get_wrangles(): wrangles = [ WOQLQuery().idgen("doc:Party", ["v:Party_A"], "v:Party_A_ID"), WOQLQuery().idgen("doc:Party", ["v:Party_B"], "v:Party_B_ID"), WOQLQuery().idgen("doc:Representative", ["v:Rep_A"], "v:Rep_A_ID"), WOQLQuery().idgen("doc:Representative", ["v:Rep_B"], "v:Rep_B_ID"), WOQLQuery().typecast("v:Distance", "xsd:decimal", "v:Similarity"), WOQLQuery().idgen("doc:Similarity", ["v:Rep_A", "v:Rep_B"], "v:Rel_ID"), WOQLQuery().concat("v:Rep_A similarity v:Distance to v:Rep_B", "v:Rel_Label") ] return wrangles
def test_woql_not_method(self): woqlObject = WOQLQuery().woql_not(WOQLQuery().triple("a", "b", "c")) woqlObjectChain = WOQLQuery().woql_not().triple("a", "b", "c") jsonObj = { 'not': [{ 'triple': ["doc:a", "scm:b", { "@language": "en", "@value": "c" }] }] } print(woqlObject.json()) assert woqlObject.json() == jsonObj assert woqlObjectChain.json() == jsonObj
def list_mother_of(child=None): ''' Return a dataframe with the name of the mother of a child. Of course, in real life, a child might be an orphan... :param child: string: woql variable or literal :return: If child is None, then a dataframe with all children and their respective mothers. Otherwise, a dataframe with the mother of the given child ''' selects = ["v:Child_Name", "v:Mother_Name" ] if child is None else ["v:Mother_Name"] # # Terminus currently has a bug with literal values in queries. Should be able to do: # WOQLQuery().triple("v:Child", "Name", child) here if child is a literal, but instead have to use @type.. # child = "v:Child_Name" if child is None else literal_string(child) q = WOQLQuery().select(*selects).woql_and( parent_of("v:Child", "v:Mother"), WOQLQuery().triple("v:Child", "Name", child), WOQLQuery().triple("v:Mother", "Name", "v:Mother_Name")) result = wary.execute_query(q, client) return pd.DataFrame( columns=selects) if is_empty(result) else wdf.query_to_df(result)
def test_min_method(self): woqlObject = WOQLQuery().add_property("P", "string").min(2) jsonObj = { "and": [{ "add_quad": ["scm:P", "rdf:type", "owl:DatatypeProperty", "db:schema"] }, { "add_quad": ["scm:P", "rdfs:range", "xsd:string", "db:schema"] }, { "add_quad": ["scm:P_min", "rdf:type", "owl:Restriction", "db:schema"] }, { "add_quad": ["scm:P_min", "owl:onProperty", "scm:P", "db:schema"] }, { "add_quad": [ "scm:P_min", "owl:minCardinality", { "@value": 2, "@type": "xsd:nonNegativeInteger" }, "db:schema" ] }] } assert woqlObject.json() == jsonObj
def test_when_method(self): woqlObject = WOQLQuery().when(True, WOQLQuery().add_class("id")) woqlObjectChain = WOQLQuery().when(True).add_class("id") jsonObj = { 'when': [{ "true": [] }, { 'add_quad': ['scm:id', 'rdf:type', 'owl:Class', 'db:schema'] }] } assert woqlObject.json() == jsonObj assert woqlObjectChain.json() == jsonObj