Example 2: Asserting and retracting triples — AllegroGraph Python client 105.1.0 documentation

# Example 2: Asserting and retracting triples

In this example we show how to create resources describing two people, Bob and Alice, by asserting triples into the repository. The example also retracts and replaces a triple. Assertions and retractions to the triple store are executed by `add()` and `remove()` methods belonging to the connection object, which we obtain by calling the `ag_connect()` function described in Example 1: Creating a repository and triple indices.

Before asserting a triple, we have to generate the URI values for the subject, predicate and object fields. The AllegroGraph Python client API predefines a number of classes and predicates for the RDF, RDFS, XSD, and OWL ontologies. `RDF.TYPE` is one of the predefined predicates we will use.

The `add()` and `remove()` methods take an optional `contexts` argument that specifies one or more subgraphs that are the target of triple assertions and retractions. When the context is omitted, triples are asserted/retracted to/from the default graph. In the example below, facts about Alice and Bob reside in the default graph.

The second example begins by calling `ag_connect()` to create the appropriate connection object, which is bound to the variable `conn`.

    from franz.openrdf.connect import ag_connect

    conn = ag_connect("python-tutorial", create=True, clear=True)

The next step is to begin assembling the URIs we will need for the new triples. The `createURI()` method generates a URI from a string. These are the subject URIs identifying the resources “Bob” and “Alice”:

    alice = conn.createURI("http://example.org/people/alice")
    bob = conn.createURI("http://example.org/people/bob")

Bob and Alice will be members of the “person” class (rdf type `person`).

    person = conn.createURI("http://example.org/ontology/Person")

Both Bob and Alice will have a “name” attribute.

    name = conn.createURI("http://example.org/ontology/name")

The name attributes will contain literal values. We have to generate the `Literal` objects from strings:

    bobsName = conn.createLiteral("Bob")
    alicesName = conn.createLiteral("Alice")

The next line prints out the number of triples currently in the repository - we expect that to be zero, since we have not yet added any triples and the `connect` function should have removed any existing statements from the repository.

    print("Triple count before inserts:", conn.size())

    Triple count before inserts: 0

Now we assert four triples, two for Bob and two more for Alice, using the connection object’s `add()` method. After the assertions, we count triples again (there should be four) and print out the triples for inspection.

    from franz.openrdf.vocabulary import RDF

    # alice is a person
    conn.add(alice, RDF.TYPE, person)
    # alice's name is "Alice"
    conn.add(alice, name, alicesName)
    # bob is a person
    conn.add(bob, RDF.TYPE, person)
    # bob's name is "Bob":
    conn.add(bob, name, bobsName)

    print("Triple count:", conn.size())
    for s in conn.getStatements(None, None, None, None):
        print(s)

The `None` arguments to the `getStatements()` method say that we don’t want to restrict what values may be present in the subject, predicate, object or context positions. Just print out all the triples.

This is the output at this point. We see four triples, two about Alice and two about Bob

    Triple count: 4
    (<http://example.org/people/alice>, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <http://example.org/ontology/Person>)
    (<http://example.org/people/alice>, <http://example.org/ontology/name>, "Alice")
    (<http://example.org/people/bob>, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, <http://example.org/ontology/Person>)
    (<http://example.org/people/bob>, <http://example.org/ontology/name>, "Bob")

We see two resources of type “person,” each with a literal name.

The next step is to demonstrate how to remove a triple. Use the `remove()` method of the connection object, and supply a triple pattern that matches the target triple. In this case we want to remove Bob’s name triple from the repository. Then we’ll count the triples again to verify that there are only three remaining.

    conn.remove(bob, name, bobsName)
    print("Triple count:", conn.size())

    Triple count: 3

A potentially less verbose way of adding triples is to use the `addData()` method of the connection object with a string containing triples in Turtle, N-Triples or another RDF format.

Let us see how the data used in this example could be added using `addData()`. We will also wrap the whole process in a function that we’ll use later:

    def add_bob_and_alice(conn):
       conn.addData("""
           @base <http://example.org/> .

           <people/alice> a <ontology/Person> ;
                          <ontology/name> "Alice" .
           <people/bob> a <ontology/Person> ;
                        <ontology/name> "Bob" .
       """)

The string used here is in the Turtle format. It is also possible to use other formats by passing the `rdf_format` argument to `addData()`.

We should check if the new function behaves as expected by creating a fresh connection (recall that the `clear` parameter causes all existing triples to be deleted):

    with ag_connect('python-tutorial', clear=True) as conn:
        add_bob_and_alice(conn)
        print("Triple count:", conn.size())

    Triple count: 4