• First Steps
  • Basic Data Operations
  • Creating Action Handlers using Action API
  • Developing a Connector
  • Working with Automation Tasks

Overview

HIRO™’s database (HIRO Graph) is a semantic graph database, which consists of vertices (containing attributes) and edges (that connect the vertices) as data items.

This tutorial will demonstrate the basic graph operations that enable you to write data to the HIRO graph database.

What we will do in this tutorial
  1. Write a new vertex to the graph

  2. Read a vertex and understand the vertex metadata

  3. Update an existing vertex

  4. Create an edge between two vertices

  5. Get related vertices

Prerequisites

  • API access to a HIRO instance

  • Authenticated HIRO session with valid access token

Please follow the tutorial First Steps with HIRO to authenticate before proceeding to use HIRO’s Graph API. We assume for this tutorial that you have created an authenticated hiro session, which is available as hiro_session object:

# Initiate session
hiro_session = initiate_hiro_session('./hiro_credentials.json')

Create a new vertex

We will create an entity in HIRO’s database called Person, together with some attributes, and then retrieve this information. To do this, we will define a function to create and read a vertex. Functions reduces repetition and make the codes reusable. By utilizing functions, any changes can be implemented in one place, without going through the whole code.

We will define a helper function called create_vertex. This function will create a vertex of a specific type in HIRO with some attributes that are passed as argument. The parameters to pass to HIRO will be:

  • entity_type: The type of entity to be created which will be in OGIT form. Among the examples are person (ogit/Person), calendar (ogit/Schedule/Calendar), and event in a calendar (ogit/Schedule/Event).

  • attributes: The attributes attached to the entity which will be in OGIT form. Some examples are first name (ogit/firstName), last name (ogit/lastName) and email (ogit/Email).

  • scope: The HIRO scope that should contain the vertex. This value will be written to the ogit/_scope attribute.

Since the entity type name contains special characters, remember to escape these special characters in the query string before sending it as URL query parameter.

Ideally you have an id for the 'data-scope' (environment) you want to interact with. If omitted the default scope of your account will be used. Please be aware, that this may lead to confusion if your account has access to multiple scopes. Therefore, it’s highly recommended defining your desired scope.

If the vertex is successfully created, the function will return the vertex id to the console, so that we can use it for the next steps. We also print the vertex id to the console for now, so that we can easily see what is happening. If the write operation fails, we will print an error message to the console.

create_vertex()
def create_vertex(entity_type, attributes):
    if hiro_session['scope']:
        attributes['ogit/_scope'] = hiro_session['scope']
    escaped_type = entity_type.replace(':', '/').replace('/', '%2F')
    response = hiro_session['session'].post(hiro_session['graph_api'] + 'new/' + escaped_type, data=json.dumps(attributes))

    if response.ok:
        print('Vertex successfully written:' + response.json()['ogit/_id'])
        return response.json()['ogit/_id']
    else:
        print(str(response.status_code) + " - " + response.text)
        print('Failed to write vertex.')

The function above can be used to write any type of vertex to the HIRO graph database. Now we define a more specific helper function to create a ogit/Person entity in HIRO Graph. This helper function will call the function create_vertex which was created earlier. The parameters that are being passed are:

  • last_name = last name of the person, to be written to the ogit/lastName attribute

  • email_address = email address of the person - this will be written as ogit/email attribute.

The entity type will be set to ogit/Person within the function.

This function will return the vertex id as received from calling the create_vertex function.

create_person()
def create_person(last_name, email_address):
    person_attributes = {'ogit/lastName': last_name, 'ogit/email': email_address}
    return create_vertex('ogit/Person', person_attributes)

As next step, we can write the first person entity to the HIRO Graph by calling the create_person() function declared before. We will call the person 'Johnny' and give it the email address 'Johnny@test.com'. When the Person object is successfully written, it will return the vertex id of the object. The vertex id is a unique id generated by the graph database.

johnny = create_person('Johnny', 'johnny@test.com')
if johnny:
	print('Johnny is now known in HIRO.')
else:
	print('Could not add person vertex.')

The result will be similar to below, which is the definition of the Person object that was created, together with its Vertex ID.

Vertex successfully written: ckd73u0ul04jo01100j5dppq7_ckeu05eeajdvt01781ax1e8v6
Johnny is now known in HIRO.

If everything succeeded the variable `johnny now contains vertex id of our created vertex.

To retrieve the Person object definition, do a GET request by specifying the query string OGIT and printing the response code as well as the object definition in a JSON format. After creating a vertex in the previous step, we can read the vertex by using the GET request in order to retrieve the vertex. Again, we define a helper function called read_vertex, so that we can read vertices more conveniently in the future.

read_vertex()
def read_vertex (vertex_id):
    response = hiro_session['session'].get(hiro_session['graph_api'] + str(vertex_id))

    if response.ok:
        return response.json()
    else:
        print (str(response.status_code) + " - " + response.text)
        print ('Failed to read vertex.')
    return None
usage
# read vertex with given id
result = read_vertex(johnny)
pp.pprint(result)

The response will be the object definition in JSON format, similar to below.

{   'ogit/_created-on': 1599572471842,
    'ogit/_creator': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
    'ogit/_creator-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
    'ogit/_graphtype': 'vertex',
    'ogit/_id': 'ckd73u0ul04jo01100j5dppq7_ckeu05eeajdvt01781ax1e8v6',
    'ogit/_is-deleted': False,
    'ogit/_modified-by': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
    'ogit/_modified-by-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
    'ogit/_modified-on': 1599572471842,
    'ogit/_organization': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nku1o70n01y50gw',
    'ogit/_owner': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nks1o70ouhlsk6a',
    'ogit/_scope': 'cjy5tvdfx0nkq1o7040e4mow0_ckd73u0ul04jo01100j5dppq7',
    'ogit/_type': 'ogit/Person',
    'ogit/_v': 1,
    'ogit/_v-id': '1599572471842-OluI9M',
    'ogit/email': 'johnny@test.com',
    'ogit/lastName': 'Johnny'}

The information above shows the metadata for the person vertex that we created previously. In Step 2, we have specified the type of vertex to be created to be ogit/Person.

Attributes that start with ogit/_ are metadata attributes with a special meaning. Most of these metadata attributes are automatically generated by HIRO; some can be set or modified by the user. Timestamps in metadata attributes use the EPOCH or UNIX timestamp. Please refer to the list below for more information on other metadata for the vertex that we created.

ogit/_creator-app and ogit/_modified-by-app : This is the ID that is referring to the Client ID when connecting to HIRO’s API. This is the same Client ID that we had read from the credentials JSON file for authentication. This attribute is also helpful when identifying which connector has created or modified an entity.

ogit/_v, and ogit/_v-id : This is the indicator for version or history when the vertex is modified. One-time modification will cause the counter to increase by 1 and accompanied by its own _v-id.

ogit/_xid : This ID acts like a ‘foreign key’ in HIRO database. It may contain the original ID made by an external app that has a different ID format than HIRO database, but still incorporated in HIRO as it may be crucial for the external app to refer to this vertex by this exact ID.

Update an existing vertex

To update an existing vertex with new or updated attributes, we need a separate function. Define a function update_vertex, that will update a vertex by doing a POST request to the server.

update_vertex()
def update_vertex (vertex_id, attributes):
    response = hiro_session['session'].post(hiro_session['graph_api'] + str(vertex_id), data=json.dumps(attributes))
    if response.ok:
        print('Vertex successfully updated:')
        pp.pprint(response.json())
    else:
        print(str(response.status_code) + " - " + response.text)
        print('Failed to update vertex.')
    return response.ok

To update a particular object which is also called a vertex, call the update_vertex function and pass the parameters Vertex ID as well as the attributes to be updated or added together with their values. In the example below, the Vertex ID object to be updated is 'johnny@test.com', to which we will add the phone number as attribute ogit/mobilePhone with the value '+1 888 123456789'.

new_attributes = {'ogit/mobilePhone': '+1 888 123456789'}
update_vertex (johnny, new_attributes)

# verify update
result = read_vertex(johnny)
    print('updated vertex')
    pp.pprint(result)

When the Vertex is successfully updated, it will respond with imformation about the modification.

Vertex successfully updated:
{   'ogit/_graphtype': 'vertex',
    'ogit/_id': 'ckd73u0ul04jo01100j5dppq7_ckeu05eeajdvt01781ax1e8v6',
    'ogit/_is-deleted': False,
    'ogit/_modified-by': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
    'ogit/_modified-by-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
    'ogit/_modified-on': 1599641083074,
    'ogit/_v': 2,
    'ogit/_v-id': '1599641083074-RZVqx4'}

To verify our update we call read_vertex` to retrieve the object definition with the newly added attribute ogit/mobilePhone: '+1 888 123456789'. We print this to the console to verify that the phone number is now stored in the graph database.

updated vertex
{   'ogit/_created-on': 1599572471842,
    'ogit/_creator': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
    'ogit/_creator-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
    'ogit/_graphtype': 'vertex',
    'ogit/_id': 'ckd73u0ul04jo01100j5dppq7_ckeu05eeajdvt01781ax1e8v6',
    'ogit/_is-deleted': False,
    'ogit/_modified-by': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
    'ogit/_modified-by-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
    'ogit/_modified-on': 1599641570097,
    'ogit/_organization': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nku1o70n01y50gw',
    'ogit/_owner': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nks1o70ouhlsk6a',
    'ogit/_scope': 'cjy5tvdfx0nkq1o7040e4mow0_ckd73u0ul04jo01100j5dppq7',
    'ogit/_type': 'ogit/Person',
    'ogit/_v': 5,
    'ogit/_v-id': '1599641570097-C1Of6P',
    'ogit/email': 'johnny@test.com',
    'ogit/lastName': 'Johnny',
    'ogit/mobilePhone': '+1 888 123456789'}

Create an edge between two vertices

To demonstrate how two vertices can be related to each other with the Edge function, create another Person as a Vertex. The code below will call the helper function create_person.

We define the function create_edge which will accept the two vertices and the edge_type as parameters. The first Vertex will have a ‘line’ going out of it and the second Vertex will have a ‘line’ going into it.

def create_edge(vertex_1, vertex_2, edge_type):
    escaped_type = edge_type.replace(':','/').replace('/', '%2F')
    body = {'out': vertex_1,
            'in': vertex_2}
    response = hiro_session['session'].post(hiro_session['graph_api'] + 'connect/' + escaped_type, json.dumps(body))
    return response.ok

In the example below, the parameters being passed are:

	vertex_1 = johnny
	vertex_2 = smith
	edge_type = ogit:follows

Which means that Johnny ‘follows’ Smith. The Edge can be verbs, like contains or likes.

smith = create_person('Smith', 'smith@test.com', scope)

if johnny and smith:
    result = create_edge(johnny, smith, 'ogit:follows')
    if result:
        print ('Successfully created edge')
    else:
        print('failed to create edge')

If the edge is successfully created, a response like below can be expected.

`Successfully created edge`

To validate that the edge has been created, we will ask the graph database to give us a list of all persons that Johnny follows.

To receive related entities we use a gremlin query. For details on how to use please see GremlinDocs. The following code retrieves all vertices that can be reached by a ogit:follows edge from our johnny entity.

    gremlin = hiro_session['graph_api'] + '/query/gremlin'
    query = 'query=out(\'ogit%2Ffollows\')'
    followers = hiro_session['session'].get(f"{gremlin}?root={johnny}&{query}")
    pprint.pprint(followers.json())

You will receive a list of followers vertices with their attributes.

{'items': [{'ogit/_created-on': 1599724886126,
            'ogit/_creator': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
            'ogit/_creator-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
            'ogit/_graphtype': 'vertex',
            'ogit/_id': 'ckd73u0ul04jo01100j5dppq7_ckewiw60ebt7e0178xrb984oh',
            'ogit/_is-deleted': False,
            'ogit/_modified-by': 'cjy5tvdfx0nkq1o7040e4mow0_cjl7uv0h3325tc506i5rv4ft8',
            'ogit/_modified-by-app': 'cju16o7cg0001mz775fnoq66i_ckdyfzx3e92sk012669wa256x',
            'ogit/_modified-on': 1599724886126,
            'ogit/_organization': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nku1o70n01y50gw',
            'ogit/_owner': 'cjy5tvdfx0nkq1o7040e4mow0_cjy5tvdfx0nks1o70ouhlsk6a',
            'ogit/_scope': 'cjy5tvdfx0nkq1o7040e4mow0_ckd73u0ul04jo01100j5dppq7',
            'ogit/_type': 'ogit/Person',
            'ogit/_v': 1,
            'ogit/_v-id': '1599724886126-DWPGBh',
            'ogit/email': 'smith@test.com',
            'ogit/lastName': 'Smith'}]}

Summary

Congratulations! You have successfully written data to HIRO, and are able to read it out.

In this tutorial, we have learned the basic operations to work with data through the HIRO API. In the next tutorial, we will learn how to create automation tasks through the API.