API Description

The Basics

The API is primarily composed by the following elements:

  • Objects:

    • Entity
    • Image
    • Video
    • Blob
    • DescriptorSet
    • Descriptor
    • BoundingBox
  • Connections: express relationship between objects.

  • Commands: perform specific actions on objects (Add/Find/Update/Delete) and the database (GetStatus/GetSchema).

Queries

ApertureDB expects users to send queries over one of its connectors [REF].

A query is composed of:

  • a string representing a JSON array of one or more commands, and
  • [optional] an “array of blobs”.

The array of blobs is used to send and receive (usually, but not always, encoded) visual data. Each element of the array can contain one of the following elements:

  • An encoded Image (either a complete image, a frame, or a bounding box)
  • An encoded Video
  • A feature vector (which is in itself an array of floating point values)
  • A user-defined blob

A query is received by ApertureDB, processed, and a response is returned. A response is composed in the same manner as a query:

  • a string representing a JSON array with the same number of elements as the query, and
  • [optional] an “array of blobs”, if blobs are returned.

A query is processed transactionally in ApertureDB: either all the commands are correctly executed, or none of them are executed and an error status is returned.

Here is an example of a query and its corresponding response, using the Python connector:

from aperturedb import Connector

db = Connector.Connector("mydatabase.mydomain.com")

query = [ {

    "AddEntity": {
        "class": "Person",
        "properties": {
            "name":      "Luis",
            "email":     "luis@aperturedata.io"
            "unique_id": 30
        }
    }
},{
    "AddImage": {
        "properties": {
            "description":   "profile photo",
            "year_captured": 2020
        }
    }
} ]

# Because we are inserting an image, a blob is expected
# in the blob_array

fd = open("luis_profile_photo.jpg", "rb")
image = fd.read()

blobs_array = []
blobs_array.append(image)

# Execute the transaction
json_response, blobs = db.query(query, blobs_array)

# json_response is a dictionary, we use a helper function to
# print the JSON array nicely.
print(db.get_last_response_str())

Output:

[ {
    "AddEntity": {
        "status": 0
    }
}, {
    "AddImage": {
        "status": 0
    }
}
]

In this example, no blob is returned as a result of the query, and the “blobs” variable will be an empty array.

Here is another example where the opposite happens: no blob is sent as part of the query, but blobs are returned as part of the response:

from aperturedb import Connector

db = Connector.Connector("mydatabase.mydomain.com")

query = [ {
    "FindImage": {
        "constraints": {
            "year_captured": [">=", 2020]
        }
        "results": {
            "list": ["year_captured", "description"]
        }
    }
}]

# Execute the transaction
json_response, blobs = db.query(query)

# json_response is a dictionary, we use a helper function to
# print the JSON array nicely.
print(db.get_last_response_str())

# Check the number of returned images:
print("Number of returned images:", len(blobs))

Output:

[ {
    "FindImage": {
        "status": 0,
        "entities": [
            {
                "year_captured": 2020,
                "description": "profile photo"
            },
            {
                "year_captured": 2021,
                "description": "party with friend"
            }
        ]
    }
}]

Number of returned images: 2

In this case, the array of blobs (“blobs” variable) will have two elements, each of which is an encoded image.

Once the data usage and data collection/preprocessing requirements of an application are understood, it is time to connect the application to ApertureDB server because ApertureDB offers the unique capabilities of storing metadata in a structured graph database as well as takes care of dealing with the actual data through one unified API, described in this documentation. We provide C++ and Python client libraries for linking with any application to enable communication with ApertureDB.

Using the API

We define a set of JSON-based API calls that allow an application to interact with ApertureDB and exploit its strengths. A user application will use the ApertureDB API by defining metadata as shown in examples above and throughout this documentation, and passing along blobs. The client side ApertureDB library provides a simple query function that accepts a JSON string with commands and an array or vector of blobs. Internally, the library wraps the query string and blob in a protobuf (choice for now) and sends it to ApertureDB. It also receives a similarly wrapped response from ApertureDB and returns it to the client. The responses will require JSON parsing on the client side, starting with the metadata string that will indicate how to interpret blobs.

Keywords

_uniqueid

Every object has an automatically generated global id associated with it. _uniqueid can be used in the “list” in a properties to retrieve the _uniqueid of the returned objects.

When used in a constraints parameter, only the “==” and the “in” operators are supported.

Note: FindConnection does not support the use of _uniqueid.