Introduction

Welcome to Aito HTTP API reference documentation.

Examples are shown in this column.

Authentication

All requests must specify an API key in the x-api-key header. There are two types of authentication keys:

  • read-only Allows only read queries. Good for sharing access to 3rd parties.
  • read/write Allows all queries.

Rate limiting

Each environment has the following rate limits:

  • 300 req/s, allowing 900 req/s bursts
  • 1 million requests per day

Please contact us at support@aito.ai, if you anticipate exceeding these limits.

Pagination

Some endpoints use pagination to limit the amount of results returned at once. The pagination is based on offset and limit parameters, similar to SQL and many other APIs.

As an example, to get the first result set of 10 items with Search query you can request:

{
  "from": "products",
  "offset": 0,
  "limit": 10
}

The response will have a total field, which tells you how many items were found in total:

{
  "offset": 0,
  "total": 81,
  "hits": [ ... ]
}

If this exceeds the amount of items in hits array, it means some results were filtered out from the response. To request the next 10 items, you can query:

{
  "from": "products",
  "offset": 10,
  "limit": 10
}

The default values for pagination parameters are the following.

ParameterDefault value
offset0
limit10

CORS

All responses are served with access-control-allow-origin: * headers. This is useful for browser applications.

Aito-specific concepts

We aim for a familiar API but in some cases Aito has a different default behavior what other databases might have.

Descending order by default

By default Aito sorts everything from the largest to the smallest. This is a design choice, dictated by the fact that within the domain of statistical reasoning: the highest values are often the most interesting ones.

For example: the items with the highest probabilities, the highest frequencies, the highest similarities, the highest mutual information, and the highest scores are often the most desired ones.

Use $asc to sort values from the smallest to the biggest, as shown in the example:

{
  "from": "products",
  "where": {
    "category.id": 89
  },
  "orderBy": {
    "$asc": "price"
  }
}

Personalisation

Aito has been designed to work well even with small data sets. One example of this is how personalised recommendations work. This is easiest to understand with an example, let's take a digital grocery store as an example.

When requesting product recommendations for a customer who's a vegetarian, Aito also considers what non-vegetarians purchase. If for example the customer would be the only vegetarian user of the grocery web shop, they could receive meat recommendations if the general average purchased a lot of meat.

This default behavior is usually a good default. In book, music, movie, and many other recommendations you commonly want to find new items, instead of getting recommendations only from your own history. However in some cases the behavior might lead to unexpected predictions. For example if we predicted how likely a vegetarian is to purchase bacon, Aito could return that it is very likely, because based on data, that's the common average.

An example recommend query could look like this:

{
  "from": "impressions",
  "where": { "session.user": "veronica" },
  "recommend": "product",
  "goal": { "purchase": true }
}

Even if we limit the data to impressions by veronica, Aito still considers other data points.

Error handling

In error cases, we return with proper HTTP status codes. Error responses:

  • 400 Bad Request Returned when there's an error with the given request payload. For example invalid query syntax.

Example error

Error returned when trying to use incorrect table name. Instead of prodjucts, it should be products.

{
  "charOffset": 17,
  "lineNumber": 3,
  "columnNumber": 13,
  "error": "failed to open 'prodjucts'",
  "status": 400,
  "message": "3:13: failed to open 'prodjucts'\n\n      \"from\": \"prodjucts\"\n              ^\n",
  "messageLines": [
    "3:13: failed to open 'prodjucts'",
    "",
    "      \"from\": \"prodjucts\"",
    "              ^"
  ]
}

Feedback & bug reports

We take our quality seriously and aim for the smoothest developer experience possible. If you run into problems, please send an email to support@aito.ai containing reproduction steps and we'll fix it as soon as possible.

Query API

The query language operations.

Search

POST /api/v1/_search

The Search-query allows you to search, filter, and order rows. You can also select only specific columns. Similar to SELECT in SQL.

The results are in descending order by default.

Aito supports intuitive links following. If your products table has a link column called category which links to another table called categories, you can simply use the following convenience in the query selection:

{
  "from": "products",
  "where": {
    "category.id": 89
  },
  "orderBy": "price"
}

Get all rows

You can easily select all rows from a table with the following query:

{
  "from": "products"
}

Note: the amount of results is limited to 10 by default.

Highlighted results

If you want to get search results with highlights, see Generic query.

Parameters
NameTypeDescription
bodyrequiredobjectSearch query
Successful responses
ResponseTypeDescription
200 OKobjectSearch results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// Declares the sorting order of the result by a field or by a // user-defined score.
"orderBy": OrderBy,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Find by id

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

You can copy-paste the example curl command to your terminal.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_search \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": { "id": "6411300000494" }
  }'

Response

{
  "offset": 0,
  "total": 1,
  "hits": [
    {
      "category": "108",
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "price": 3.95,
      "tags": "coffee"
    }
  ]
}

Where price is greater than

You can copy-paste the example curl command to your terminal.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_search \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": {
      "price": { "$gt": 1.5 }
    },
    "limit": 2
  }'

Response

{
  "offset": 0,
  "total": 21,
  "hits": [
    {
      "category": "101",
      "id": "6437002001454",
      "name": "VAASAN Ruispalat 660g 12 pcs fullcorn rye bread",
      "price": 1.69,
      "tags": "gluten bread"
    },
    {
      "category": "101",
      "id": "6411402202208",
      "name": "Fazer Puikula fullcorn rye bread 9 pcs/500g",
      "price": 1.85,
      "tags": "gluten bread"
    }
  ]
}

Where price is greater than

You can copy-paste the example curl command to your terminal.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_search \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": {
      "price": { "$gt": 1.5 }
    },
    "limit": 2
  }'

Response

{
  "offset": 0,
  "total": 21,
  "hits": [
    {
      "category": "101",
      "id": "6437002001454",
      "name": "VAASAN Ruispalat 660g 12 pcs fullcorn rye bread",
      "price": 1.69,
      "tags": "gluten bread"
    },
    {
      "category": "101",
      "id": "6411402202208",
      "name": "Fazer Puikula fullcorn rye bread 9 pcs/500g",
      "price": 1.85,
      "tags": "gluten bread"
    }
  ]
}

Find products with search term

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_search \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": {
      "name": { "$match": "coffee" }
    }
  }'

Response

{
  "offset": 0,
  "total": 4,
  "hits": [
    {
      "category": "108",
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "price": 3.95,
      "tags": "coffee"
    },
    {
      "category": "108",
      "id": "6420101441542",
      "name": "Kulta Katriina filter coffee 500g",
      "price": 3.45,
      "tags": "coffee"
    },
    {
      "category": "108",
      "id": "6411300164653",
      "name": "Juhla Mokka Dark Roast coffee 500g hj",
      "price": 3.95,
      "tags": "coffee"
    },
    {
      "category": "108",
      "id": "6410405181190",
      "name": "Pirkka Costa Rica filter coffee 500g UTZ",
      "price": 2.89,
      "tags": "coffee pirkka"
    }
  ]
}

More complex where proposition

Find all products priced over 1.5€, which have tag drink or their name matches to coffee.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_search \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": {
      "$and": [
        {
          "$or": [
            {
              "tags": { "$has": "drink" }
            },
            {
              "name": { "$match": "coffee" }
            }
          ]
        },
        {
          "price": { "$gt": 1.5 }
        }
      ]
    },
    "limit": 2
  }'

Response

{
  "offset": 0,
  "total": 6,
  "hits": [
    {
      "category": "104",
      "id": "6408430000258",
      "name": "Valio eila™ Lactose-free semi-skimmed milk drink 1l",
      "price": 1.95,
      "tags": "lactose-free drink"
    },
    {
      "category": "108",
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "price": 3.95,
      "tags": "coffee"
    }
  ]
}

Predict

POST /api/v1/_predict

The Predict query is used to predict the likelihood of a feature given a hypothesis. For example predict what other products user could add into their ecommerce shopping cart, based on the existing cart. To understand why Aito predicts certain results, you can select "$why".

Related information

  • The exclusiveness option is explained in Exclusiveness chapter.
  • The chapter Personalisation also explains a characteristic of predictions in Aito.
Parameters
NameTypeDescription
bodyrequiredobjectPredict query
Successful responses
ResponseTypeDescription
200 OKobjectPrediction results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// PropositionSet expression is used to describe a collection // of propositions.
"predict": PropositionSet,
// When true, Aito considers that only one feature can be true // at the same time and that one feature will be true. // Default: true
"exclusiveness": boolean,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Predict purchase likelihood

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we're predicting how likely the customer with username larry would purchase the product "Finnish bread cheese 120g lactose-free" (6410405197764). In the example data, Larry purchases a lot of lactose-free products, but has never purchased any cheese. Aito detects that the "lactose-free" tag is a commonly occuring feature in the data, and predicts that Larry would also quite likely purchase the cheese.

The query format depends on how the data has been structured in Aito (schema). In the example dataset impressions table contains each individual product a user has seen in their shop visit (=session) and if they bought the product or not.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_predict \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "larry", "product.id": "6410405216120" },
    "predict": "purchase"
  }'

Response

{
  "offset": 0,
  "total": 2,
  "hits": [
    { "$p": 0.7841966771599878, "field": "purchase", "feature": true },
    { "$p": 0.21580332284001236, "field": "purchase", "feature": false }
  ]
}

Explain the prediction

Same example as above, but we ask Aito to explain why it predicted the results. To understand the response, see "$why" section.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_predict \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "larry", "product.id": "6410405216120" },
    "select": ["$why"],
    "predict": "purchase"
  }'

Response

{
  "offset": 0,
  "total": 2,
  "hits": [
    {
      "$why": {
        "type": "product",
        "factors": [
          { "type": "baseP", "value": 0.5 },
          { "type": "normalizer", "name": "exclusiveness", "value": 1 },
          {
            "type": "relatedVariableLift",
            "variable": "product.id:6410405216120",
            "value": 1.5683933543199755
          }
        ]
      }
    },
    {
      "$why": {
        "type": "product",
        "factors": [
          { "type": "baseP", "value": 0.5 },
          { "type": "normalizer", "name": "exclusiveness", "value": 1 },
          {
            "type": "relatedVariableLift",
            "variable": "product.id:6410405216120",
            "value": 0.4316066456800247
          }
        ]
      }
    }
  ]
}

Example request

In the example we're predicting three suitable tags for a hypothetical new product based on its name. Tags are predicted based on what tags existing products have.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_predict \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": { "name": "Hovis Seed Sensations Seven Seeds Original 800g" },
    "predict": "tags",
    "exclusiveness": false,
    "limit": 3
  }'

Response

{
  "offset": 0,
  "total": 22,
  "hits": [
    { "$p": 0.36, "field": "tags", "feature": "pirkka" },
    { "$p": 0.32, "field": "tags", "feature": "food" },
    { "$p": 0.28, "field": "tags", "feature": "meat" }
  ]
}

Recommend

POST /api/v1/_recommend

Recommend can be used to make a recommendation, that optimizes a goal in a specified situation. For example, you could ask Aito to choose a product, which maximises the click likelihood, when user id equals 4543.

Recommend differs from predict and match in the following way: recommend always optimizes a goal, while predict and match merely mimics the existing behavior patterns in the data. As an example, consider the problem matching employees to projects. With predict and match: you can mimic the way the projects are staffed currently, and Aito will mimic both the good and the bad staffing practices. With recommend, Aito seeks to maximize the success rate and avoid decisions that lead to bad outcomes, even if these decisions were a popular practice.

The chapter Personalisation also explains a characteristic of the recommendations.

Parameters
NameTypeDescription
bodyrequiredobjectRecommend query
Successful responses
ResponseTypeDescription
200 OKobjectRecommend results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// Get expression defines what items are returned as query // results.
"recommend": Get,
// Specifies a goal to maximize.
"goal": Goal,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Recommend top 5 products for a customer

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we're recommending the top 5 products which veronica (user id) would most likely to purchase based on her behavior history stored in impressions table. The table contains information of which products she has seen and which of those where bought.

This query could be used to generate campaign email which recommends relevant products for a customer.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_recommend \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "veronica" },
    "recommend": "product",
    "goal": { "purchase": true },
    "limit": 5
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$p": 0.17833437799888702,
      "category": "100",
      "id": "6410405060457",
      "name": "Pirkka bio cherry tomatoes 250g international 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka tomato"
    },
    {
      "$p": 0.17833437799888702,
      "category": "100",
      "id": "6410405093677",
      "name": "Pirkka iceberg salad Finland 100g 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000818700008",
      "name": "Pirkka banana",
      "price": 0.166,
      "tags": "fresh fruit pirkka"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000604700007",
      "name": "Cucumber Finland",
      "price": 0.9765,
      "tags": "fresh vegetable"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000503600002",
      "name": "Chiquita banana",
      "price": 0.28054,
      "tags": "fresh fruit"
    }
  ]
}

Recommend top products with additional filtering

This example is the same as above, but we're adding an additional criteria: the product name should match to 'Banana' search query.

This query could be used to build a personalised search functionality.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_recommend \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": {
      "product.name": { "$match": "Banana" },
      "session.user": "veronica"
    },
    "recommend": "product",
    "goal": { "purchase": true },
    "limit": 5
  }'

Response

{
  "offset": 0,
  "total": 2,
  "hits": [
    {
      "$p": 0.49999999999999994,
      "category": "100",
      "id": "2000818700008",
      "name": "Pirkka banana",
      "price": 0.166,
      "tags": "fresh fruit pirkka"
    },
    {
      "$p": 0.49999999999999994,
      "category": "100",
      "id": "2000503600002",
      "name": "Chiquita banana",
      "price": 0.28054,
      "tags": "fresh fruit"
    }
  ]
}

Evaluate

POST /api/v1/_evaluate

Evaluates performance and accuracy of Predict, Match, and Similarity queries.

Evaluate operation is in alpha stage. The syntax might change in the future.

The operation splits your data into two categories:

  • Training data. Will be used to train Aito.

  • Test data. Will be used to test how Aito would perform with the given training data.

    You can just specify test data, and Aito will automatically use the rest for training.

After that, a simulated evaluation scenario is ran: Aito simulates inserting the training data in to a table and then runs the given query for each sample (=row in a table) in the test data and measures how good the results were.

Parameters
NameTypeDescription
bodyrequiredobjectEvaluate query
Successful responses
ResponseTypeDescription
200 OKobjectEvaluate results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"train": Proposition,
// Proposition expression describes a fact, or a statement.
"test": Proposition,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Operation to be evaluated.
"evaluate": EvaluateOperation
}
Response format
{
// The accuracy of predictions.
"accuracy": number,
// The amount of samples used for training.
"trainSamples": number,
// The amount of samples used for testing.
"testSamples": number,
// The amount of samples used for testing. Alias for // `testSamples`.
"n": number,
// The mean execution time of the queries in milliseconds.
"meanMs": number,
// The mean execution time of the queries in microseconds.
"meanUs": number,
// The mean execution time of the queries in nanoseconds.
"meanNs": number,
// The time spent for warm-up of indexes and caches for the // given query in milliseconds.
"warmingMs": number,
// The simulated accuracy of predictions based on taking the // most frequent value. This is not the actual Aito accuracy, // but useful to understand how much better results Aito can // provide.
"baseAccuracy": number,
// How much better results Aito was able to provide compared to // a naive prediction. `accuracy - baseAccuracy`.
"accuracyGain": number,
// The mean geometric probability of the predictions.
"geomMeanP": number,
// Base geometric mean probability.
"baseGmp": number,
// Complement of `accuracy` (=`1 - accuracy`).
"error": number,
// Complement of `baseAccuracy` (=`1 - baseAccuracy`).
"baseError": number,
// Entropy.
"h": number,
// A measurement which describes the quality of probabilities // (=`h - mxe`).
"informationGain": number,
"baseMeanRank": number,
"geomMeanLift": number,
"meanRank": number,
"rankGain": number,
"features": number,
"mxe": number
}

Example request

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we're evaluating how good results Aito provides when we predict tags for a new hypothetical product. The results give us the accuracy and performance of the prediction example shown in Predict operation's documentation.

$index is a built-in variable which tells the insertion index of a row. In the example, we select 1/4 of the rows in products table to be used as test data. The rest of the rows are automatically used as training data.

Aito iterates through each product in the test data, and tests how accurate the prediction of tags for a given product name was.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_evaluate \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "test": {
      "$index": {
        "$mod": [4, 0]
      }
    },
    "evaluate": {
      "where": ["name"],
      "predict": "tags"
    }
  }'

Response

{
  "mxe": 0.3454830744944941,
  "baseAccuracy": 0.2727272727272727,
  "meanUs": 9146.138272727274,
  "accuracyGain": 0.6363636363636364,
  "n": 11,
  "rankGain": 2.545454545454545,
  "warmingMs": 0,
  "features": 249,
  "accuracy": 0.9090909090909091,
  "trainSamples": 31,
  "geomMeanP": 0.7870443971402789,
  "baseGmp": 0.2530509367103527,
  "meanMs": 9.146138272727274,
  "error": 0.09090909090909094,
  "baseError": 0.7272727272727273,
  "testSamples": 11,
  "geomMeanLift": 3.1102212359764785,
  "meanRank": 1.9090909090909092,
  "meanNs": 9146138.272727273,
  "h": 1.9825002801539287,
  "informationGain": 1.6370172056594348,
  "baseMeanRank": 4.454545454545454
}

Similarity

POST /api/v1/_similarity

Similarity can be used to return entries, that are similar to the given sample object (or row). The sample object can be either a complete or a partial row.

Similarity operation uses TF-IDF for scoring the documents.

The chapter Personalisation also explains a characteristic of the similarity model.

Parameters
NameTypeDescription
bodyrequiredobjectSimilarity query
Successful responses
ResponseTypeDescription
200 OKobjectSimilarity results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// Proposition expression describes a fact, or a statement.
"similarity": Proposition,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Example request

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we're finding similar products to a given existing product. Aito assumes that the given sample object is a hypothetical new object, which is why in this example the exact same product is also in the results.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_similarity \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "similarity": {
      "category": "108",
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "price": 3.95,
      "tags": "coffee"
    },
    "limit": 3
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$score": 6.046201706453473,
      "category": "108",
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "price": 3.95,
      "tags": "coffee"
    },
    {
      "$score": 3.189723241114507,
      "category": "108",
      "id": "6411300164653",
      "name": "Juhla Mokka Dark Roast coffee 500g hj",
      "price": 3.95,
      "tags": "coffee"
    },
    {
      "$score": 1.8629019506399436,
      "category": "108",
      "id": "6420101441542",
      "name": "Kulta Katriina filter coffee 500g",
      "price": 3.45,
      "tags": "coffee"
    }
  ]
}

Example request

In the example we're finding similar products based on just a product name.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_similarity \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "similarity": { "name": "Hovis Seed Sensations Seven Seeds Original 800g" },
    "limit": 3
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$score": 1,
      "category": "100",
      "id": "2000818700008",
      "name": "Pirkka banana",
      "price": 0.166,
      "tags": "fresh fruit pirkka"
    },
    {
      "$score": 1,
      "category": "100",
      "id": "2000604700007",
      "name": "Cucumber Finland",
      "price": 0.9765,
      "tags": "fresh vegetable"
    },
    {
      "$score": 1,
      "category": "100",
      "id": "6410405060457",
      "name": "Pirkka bio cherry tomatoes 250g international 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka tomato"
    }
  ]
}

Match

POST /api/v1/_match

The Match query can be used to predict:

  1. a row behind a link
  2. the value inside a text field
  3. field feature

The query is conceptually similar to Predict.

Differences to Predict

While match is similar to Predict query, there are fine-grained differences explained below.

Predict returns features, while match can return values

Match can return A) the row behind a link or B) the value inside a text field. If match is done against non-analyzed field, it works similarly to predict, except the inference algorithm is somewhat different

The inference model is different

Predict treats features as 'black boxes', and it does statistical reasoning purely based on the feature's own statistics. Match does 'glass box' statistical reasoning by using all the features found behind the link or within a field.

For example, if you are predicting a product, the predict-query will look at the histories of the each individual product ids. If there is no history for the product, Aito will not be a ble to do proper inference. On the other hand, if you are matching the product, Aito will look at the product category, title and description. This enables Aito to match products, it has never seen before, as long as it is familiar with its internal features

The chapter Personalisation also explains a characteristic of the matching.

Parameters
NameTypeDescription
bodyrequiredobjectMatch query
Successful responses
ResponseTypeDescription
200 OKobjectMatch results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Get expression defines what items are returned as query // results.
"match": Get,
// PropositionSet expression is used to describe a collection // of propositions.
"basedOn": PropositionSet,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Match user to products

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we're matching a user to products.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_match \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "larry" },
    "match": "product",
    "limit": 5
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$p": 0.34552951423201694,
      "category": "104",
      "id": "6410405216120",
      "name": "Pirkka lactose-free semi-skimmed milk drink 1l",
      "price": 1.25,
      "tags": "lactose-free drink pirkka"
    },
    {
      "$p": 0.1280610758088988,
      "category": "104",
      "id": "6408430000258",
      "name": "Valio eila™ Lactose-free semi-skimmed milk drink 1l",
      "price": 1.95,
      "tags": "lactose-free drink"
    },
    {
      "$p": 0.03832437215991153,
      "category": "100",
      "id": "6410405060457",
      "name": "Pirkka bio cherry tomatoes 250g international 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka tomato"
    },
    {
      "$p": 0.036592197147034176,
      "category": "100",
      "id": "2000604700007",
      "name": "Cucumber Finland",
      "price": 0.9765,
      "tags": "fresh vegetable"
    },
    {
      "$p": 0.03312784712127946,
      "category": "107",
      "id": "6410400033524",
      "name": "Pirkka frozen potato-onion mix 500g",
      "price": 0.79,
      "tags": "food carbohydrate pirkka"
    }
  ]
}

Relate

POST /api/v1/_relate

The Relate-query provides statistical information of the relationship between a pair of features (columns in tables). It can be used to for example to find causation and correlation.

The hits are by default ordered by relation.mi field. It indicates how strong the correlation is.

Parameters
NameTypeDescription
bodyrequiredobjectRelate query
Successful responses
ResponseTypeDescription
200 OKobjectRelate results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// PropositionSet expression is used to describe a collection // of propositions.
"relate": PropositionSet,
// To be clarified.
"orderBy": RelateOrderBy,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

What features of products affect purchasing

The examples are using the dataset of our grocery store demo app. To get deeper understanding of the data context, you can check out the demo app.

In the example we ask Aito to explain what factors of products affect to people purchasing them. With $exists, we tell Aito to get all properties of the product (impressions table links to the products table), and relate those to the condition {"purchase": true }.

The response may seem overwhelming but it contains a lot of useful information.

When looking at the second hit, we can see that when product.tags:vegetable, the "lift" value is high (compared to 1.0). It means that when the product tags contain a tag vegetable, it is ~1.9x more likely that the product will be purchased compared to the average product (=base probability).

The lift is calculated with the formula: the probability of the condition { "purchase": true} divided by the average probability of the condition. The formula with the correct field names is: ps.pOnCondition / ps.p.

In the example data set, people purchase 50% of products they see. This causes the base probability to be 0.5.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_relate \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "$exists": "product" },
    "relate": [
      { "purchase": true }
    ],
    "limit": 2
  }'

Response

{
  "offset": 0,
  "total": 124,
  "hits": [
    {
      "related": "purchase:true",
      "lift": 0.25611447987925023,
      "condition": "product.name:fazer",
      "fs": {
        "f": 1680,
        "fOnCondition": 40,
        "fOnNotCondition": 1640,
        "fCondition": 320,
        "n": 3360
      },
      "ps": {
        "p": 0.5,
        "pOnCondition": 0.12805723993962512,
        "pOnNotCondition": 0.5391517423843831,
        "pCondition": 0.09523781551820762
      },
      "info": {
        "h": 1,
        "mi": 0.44791401701173766,
        "miTrue": -0.25165031157192846,
        "miFalse": 0.6995643285836661
      },
      "relation": {
        "n": 3360,
        "varFs": [320, 1680],
        "stateFs": [1400, 280, 1640, 40],
        "mi": 0.046664130610992574
      }
    },
    {
      "related": "purchase:true",
      "lift": 0.18455932520038865,
      "condition": "product.name:puikula",
      "fs": {
        "f": 1680,
        "fOnCondition": 16,
        "fOnNotCondition": 1664,
        "fCondition": 184,
        "n": 3360
      },
      "ps": {
        "p": 0.5,
        "pOnCondition": 0.09227966260019432,
        "pOnNotCondition": 0.5236210173698082,
        "pCondition": 0.05476177303338896
      },
      "info": {
        "h": 1,
        "mi": 0.5559663947062397,
        "miTrue": -0.2249633720193698,
        "miFalse": 0.7809297667256094
      },
      "relation": {
        "n": 3360,
        "varFs": [184, 1680],
        "stateFs": [1512, 168, 1664, 16],
        "mi": 0.03196802243310381
      }
    }
  ]
}

Generic query

POST /api/v1/_query

Generic query is a powerful expert interface, providing the functionality of every other query type in the API. Search, Similarity, Match, and Recommend can be seen as convenience APIs for the generic query.

The query format resembles the Search-query, except that it supports a "get" statement. Since this endpoint provides functionality of all other queries, "get": "product" is used as a replacement for "predict": "product", "recommend": "product", and "match": "product" counterparts.

The chapter Personalisation also explains a characteristic of the inference model.

Namespace shifting of "get"

The "get" operation changes the namespaces of "select" and "orderBy" operations. The namespace is changed from the "from" table to the linked table (specified with "get").

As an example, think of this query. The impressions table has a column called product which links to a row in products table. The price and title fields are columns of products.

{
  "from": "impressions",
  "where": {
    "query": "macbook air 2018"
  },
  "get": "product",
  "orderBy": ["price"],
  "select": ["title", "$highlight"]
}

When using "select" and "orderBy", we are already in the products table namespace, instead of having to use product.title or product.price.

Related information

Parameters
NameTypeDescription
bodyrequiredobjectGeneric query
Successful responses
ResponseTypeDescription
200 OKobjectQuery results
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition,
// Get expression defines what items are returned as query // results.
"get": Get,
// To be clarified.
"orderBy": QueryOrderBy,
// Describes the fields and/or built-in attributes to return.
"select": Selection,
// Skips the given amount of entries from the beginning. // Default: 0
"offset": integer,
// The maximum amount of entries to be returned. // Default: 10
"limit": integer
}
Response format
{
// The amount of entries which were skipped from the beginning // of pagination. // Default: 0
"offset": integer,
// The total amount of hits returned.
"total": integer,
// Entries returned for a given query.
"hits": Hits
}

Search query

Simple search query with the generic query.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": { "id": "6410402010318" }
  }'

Response

{
  "offset": 0,
  "total": 1,
  "hits": [
    {
      "category": "115",
      "id": "6410402010318",
      "name": "Pirkka tuna fish pieces in oil 200g/150g",
      "price": 1.69,
      "tags": "meat food protein pirkka"
    }
  ]
}

Search query with highlighted results

Search query which returns related products ordered by similarity. The response also contains the highlighted words which matched to the search term.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": {
      "name": { "$match": "coffee" }
    },
    "select": ["id", "name", "tags", "price", "$score", "$highlight"],
    "orderBy": "$similarity"
  }'

Response

{
  "offset": 0,
  "total": 4,
  "hits": [
    {
      "id": "6411300000494",
      "name": "Juhla Mokka coffee 500g sj",
      "tags": "coffee",
      "price": 3.95,
      "$score": 1.3346734907091136,
      "$highlight": [
        {
          "score": 1.1194647495169912,
          "field": "name",
          "highlight": "Juhla Mokka <font color=\"green\">coffee</font> 500g sj"
        }
      ]
    },
    {
      "id": "6420101441542",
      "name": "Kulta Katriina filter coffee 500g",
      "tags": "coffee",
      "price": 3.45,
      "$score": 1.3346734907091136,
      "$highlight": [
        {
          "score": 1.1194647495169912,
          "field": "name",
          "highlight": "Kulta Katriina filter <font color=\"green\">coffee</font> 500g"
        }
      ]
    },
    {
      "id": "6411300164653",
      "name": "Juhla Mokka Dark Roast coffee 500g hj",
      "tags": "coffee",
      "price": 3.95,
      "$score": 1.3018159138535317,
      "$highlight": [
        {
          "score": 1.1194647495169912,
          "field": "name",
          "highlight": "Juhla Mokka Dark Roast <font color=\"green\">coffee</font> 500g hj"
        }
      ]
    },
    {
      "id": "6410405181190",
      "name": "Pirkka Costa Rica filter coffee 500g UTZ",
      "tags": "coffee pirkka",
      "price": 2.89,
      "$score": 1.288697684625764,
      "$highlight": [
        {
          "score": 1.1194647495169912,
          "field": "name",
          "highlight": "Pirkka Costa Rica filter <font color=\"green\">coffee</font> 500g UTZ"
        }
      ]
    }
  ]
}

Generic similarity query

In the example we're finding similar products based on the given hypothetical new product name.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "orderBy": {
      "$similarity": { "name": "Atria bratwurst 175g" }
    },
    "limit": 2
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$score": 1.2962730583229296,
      "category": "102",
      "id": "6407870070333",
      "name": "Atria lauantaimakkara bread sausage 225g",
      "price": 0.89,
      "tags": "meat sausage with-bread"
    },
    {
      "$score": 1.2962730583229296,
      "category": "102",
      "id": "6407870071224",
      "name": "Atria Gotler ham sausage 300g",
      "price": 1.75,
      "tags": "meat sausage with-bread"
    }
  ]
}

Generic predict query

In the example we're predicting which tags a new hypothetical product could have.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "products",
    "where": { "name": "Atria bratwurst 175g" },
    "get": "tags.$feature",
    "orderBy": "$p",
    "limit": 5
  }'

Response

{
  "offset": 0,
  "total": 22,
  "hits": [
    { "$p": 0.42022353218407604, "field": "", "feature": "sausage" },
    { "$p": 0.2869017797908451, "field": "", "feature": "meat" },
    { "$p": 0.02706911540368487, "field": "", "feature": "protein" },
    { "$p": 0.023685475978224263, "field": "", "feature": "drink" },
    { "$p": 0.023685475978224263, "field": "", "feature": "lactose" }
  ]
}

Recommend products which a customer would most likely purchase

In the example we're finding the top 5 products which veronica (user id) would most likely to purchase based on her behavior history stored in impressions table.

This example is the the same as in the documentation of Recommendation endpoint, but made with the generic query.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "veronica" },
    "get": "product",
    "orderBy": {
      "$p": {
        "$context": { "purchase": true }
      }
    },
    "limit": 5
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$p": 0.17833437799888702,
      "category": "100",
      "id": "6410405060457",
      "name": "Pirkka bio cherry tomatoes 250g international 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka tomato"
    },
    {
      "$p": 0.17833437799888702,
      "category": "100",
      "id": "6410405093677",
      "name": "Pirkka iceberg salad Finland 100g 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000818700008",
      "name": "Pirkka banana",
      "price": 0.166,
      "tags": "fresh fruit pirkka"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000604700007",
      "name": "Cucumber Finland",
      "price": 0.9765,
      "tags": "fresh vegetable"
    },
    {
      "$p": 0.10485901383013654,
      "category": "100",
      "id": "2000503600002",
      "name": "Chiquita banana",
      "price": 0.28054,
      "tags": "fresh fruit"
    }
  ]
}

Query with custom scoring

In the example we're finding the top 5 products which veronica (user id) would most likely to purchase but in addition we're boosting products which have higher price. This would recommend products which are relevant for the user but also bring higher revenue to the shop. This demonstrates a situation where multiple factors should be considered in recommendations.

curl -X POST \
  https://aito-grocery-store.api.aito.ai/api/v1/_query \
  -H 'content-type: application/json' \
  -H 'x-api-key: bc4Ck3nDwM1ILVjNahNJL8hPEAzCes8t2vGMUyo9' \
  -d '
  {
    "from": "impressions",
    "where": { "session.user": "veronica" },
    "get": "product",
    "orderBy": {
      "$multiply": [
        {
          "$p": {
            "$context": { "purchase": true }
          }
        },
        "price"
      ]
    },
    "limit": 3
  }'

Response

{
  "offset": 0,
  "total": 42,
  "hits": [
    {
      "$score": 0.23005134761856424,
      "category": "100",
      "id": "6410405060457",
      "name": "Pirkka bio cherry tomatoes 250g international 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka tomato"
    },
    {
      "$score": 0.23005134761856424,
      "category": "100",
      "id": "6410405093677",
      "name": "Pirkka iceberg salad Finland 100g 1st class",
      "price": 1.29,
      "tags": "fresh vegetable pirkka"
    },
    {
      "$score": 0.1122714959702717,
      "category": "108",
      "id": "6410405181190",
      "name": "Pirkka Costa Rica filter coffee 500g UTZ",
      "price": 2.89,
      "tags": "coffee pirkka"
    }
  ]
}

Database API

Operations which manipulate the Aito database.

Get database schema

GET /api/v1/schema

Returns the schema for the database.

Successful responses
ResponseTypeDescription
200 OKobjectThe current active schema
Response format
{
// Database tables. Each key-value pair is a table name and the // table schema. Required.
"schema": {
// Any schema which is a valid Aito table schema.
"<yourTableName>": UserDefinedTableSchema
}
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X GET \
  https://your-env-name.api.aito.ai/api/v1/schema \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "schema": {
    "products": {
      "type": "table",
      "columns": {
        "id": { "type": "Int", "nullable": false },
        "name": { "type": "String", "nullable": false },
        "price": { "type": "Decimal", "nullable": false },
        "description": {
          "type": "Text",
          "nullable": false,
          "analyzer": "English"
        }
      }
    }
  }
}

Create database schema

PUT /api/v1/schema

Creates or updates the schema for the entire database. The operation works like a PATCH operation.

The operation deletes all data of any updated tables! The action is irreversible.

Parameters
NameTypeDescription
bodyrequiredobjectAny schema which is a valid Aito database schema
Successful responses
ResponseTypeDescription
200 OKobjectThe current active schema
Request format
{
// Database tables. Each key-value pair is a table name and the // table schema. Required.
"schema": {
// Any schema which is a valid Aito table schema.
"<yourTableName>": UserDefinedTableSchema
}
}
Response format
{
// Database tables. Each key-value pair is a table name and the // table schema. Required.
"schema": {
// Any schema which is a valid Aito table schema.
"<yourTableName>": UserDefinedTableSchema
}
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X PUT \
  https://your-env-name.api.aito.ai/api/v1/schema \
  -H 'content-type: application/json' \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY' \
  -d '
  {
    "schema": {
      "products": {
        "type": "table",
        "columns": {
          "id": { "type": "Int" },
          "name": { "type": "String" },
          "price": { "type": "Decimal" },
          "description": { "type": "Text", "analyzer": "English" }
        }
      }
    }
  }'

Response

{
  "schema": {
    "products": {
      "type": "table",
      "columns": {
        "id": { "type": "Int" },
        "name": { "type": "String" },
        "price": { "type": "Decimal" },
        "description": { "type": "Text", "analyzer": "English" }
      }
    }
  }
}

Delete database

DELETE /api/v1/schema

Deletes the entire database schema.

The operation deletes all data and contents inside! The action is irreversible.

Successful responses
ResponseTypeDescription
200 OKobjectThe summary of deletion
Response format
{
// Array of table names deleted. Required.
"deleted": [string, ...]
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X DELETE \
  https://your-env-name.api.aito.ai/api/v1/schema \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "deleted": ["products"]
}

Get table schema

GET /api/v1/schema/{table}

Returns the schema for the specified table.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
Successful responses
ResponseTypeDescription
200 OKobjectThe current schema for the table
Response format
{
// Type of the database schema item. Currently only 'table' is // accepted.
"type": string,
// Table columns. Each key-value pair is a column name and the // column type.
"columns": {
// Type of the column.
"<yourColumnName>": ColumnType
}
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X GET \
  https://your-env-name.api.aito.ai/api/v1/schema/products \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "type": "table",
  "columns": {
    "id": { "type": "Int", "nullable": false },
    "name": { "type": "String", "nullable": false },
    "price": { "type": "Decimal", "nullable": false },
    "description": { "type": "Text", "nullable": false, "analyzer": "English" }
  }
}

Create table schema

PUT /api/v1/schema/{table}

Updates a schema of a speficied table.

The operation deletes all data and contents in the table! The action is irreversible.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
bodyrequiredobjectAny schema which is a valid Aito table schema
Successful responses
ResponseTypeDescription
200 OKobjectThe current schema for the table
Request format
{
// Type of the database schema item. Currently only 'table' is // accepted.
"type": string,
// Table columns. Each key-value pair is a column name and the // column type.
"columns": {
// Type of the column.
"<yourColumnName>": ColumnType
}
}
Response format
{
// Type of the database schema item. Currently only 'table' is // accepted.
"type": string,
// Table columns. Each key-value pair is a column name and the // column type.
"columns": {
// Type of the column.
"<yourColumnName>": ColumnType
}
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X PUT \
  https://your-env-name.api.aito.ai/api/v1/schema/products \
  -H 'content-type: application/json' \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY' \
  -d '
  {
    "type": "table",
    "columns": {
      "id": { "type": "Int" },
      "name": { "type": "String" },
      "price": { "type": "Decimal" },
      "description": { "type": "Text", "analyzer": "English" }
    }
  }'

Response

{
  "schema": {
    "products": {
      "type": "table",
      "columns": {
        "id": { "type": "Int", "nullable": false },
        "name": { "type": "String", "nullable": false },
        "price": { "type": "Decimal", "nullable": false },
        "description": {
          "type": "Text",
          "nullable": false,
          "analyzer": "English"
        }
      }
    }
  }
}

Delete table

DELETE /api/v1/schema/{table}

Deletes a single table in the schema.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
Successful responses
ResponseTypeDescription
200 OKobjectThe summary of deletion
Response format
{
// Array of table names deleted. Required.
"deleted": [string, ...]
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X DELETE \
  https://your-env-name.api.aito.ai/api/v1/schema/products \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "deleted": ["products"]
}

Insert entry

POST /api/v1/data/{table}

Inserts entry to a table.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
bodyrequiredobjectAny object which is valid according to the database schema
Successful responses
ResponseTypeDescription
200 OKobjectThe created entry
Request format
Response format

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X POST \
  https://your-env-name.api.aito.ai/api/v1/data/products \
  -H 'content-type: application/json' \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY' \
  -d '
  {
    "id": 1,
    "name": "Apple iPhone 8 64 Gt, spacegray",
    "price": 648.9,
    "description": "A11 processor and wireless charging."
  }'

Response

{
  "id": 1,
  "name": "Apple iPhone 8 64 Gt, spacegray",
  "price": 648.9,
  "description": "A11 processor and wireless charging."
}

Insert multiple entries

POST /api/v1/data/{table}/batch

Imports multiple entries into the database. The batch import can be used to upload multiple entries to a single table. The payload needs to be a valid JSON array (instead of ndjson).

Note: batch API supports max 10MB payloads.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
bodyrequiredarrayThe request body
Successful responses
ResponseTypeDescription
200 OKobjectSummary of inserted entries
Request format
Response format
{
// How many entries were inserted. Required.
"entries": integer,
// Status text. Required.
"status": string
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X POST \
  https://your-env-name.api.aito.ai/api/v1/data/products/batch \
  -H 'content-type: application/json' \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY' \
  -d '
  [
    {
      "id": 1,
      "name": "Apple iPhone 8 64 Gt, spacegray",
      "price": 648.9,
      "description": "A11 processor and wireless charging."
    },
    {
      "id": 2,
      "name": "Apple iPhone X 32 GB, space gray",
      "price": 1048.9,
      "description": "All‑screen design. Longest battery life ever in an iPhone."
    },
    {
      "id": 3,
      "name": "Samsung Galaxy S9",
      "price": 698.2,
      "description": "The Camera. Reimagined."
    }
  ]'

Response

{
  "status": "ok",
  "entries": 3
}

Delete entries

POST /api/v1/data/_delete

Deletes entries with a Search-like interface. You can describe the target table and filters for which entries to delete.

Warning: an empty proposition will match and delete everything!

Parameters
NameTypeDescription
bodyrequiredobjectTo be clarified
Successful responses
ResponseTypeDescription
200 OKobjectSummary of deleted content
Request format
{
// From expression declares the examined table.
"from": From,
// Proposition expression describes a fact, or a statement.
"where": Proposition
}
Response format
{
// How many rows was deleted. Required.
"total": integer
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X POST \
  https://your-env-name.api.aito.ai/api/v1/data/_delete \
  -H 'content-type: application/json' \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY' \
  -d '
  {
    "from": "products",
    "where": { "id": 1 }
  }'

Response

{
  "total": 1
}

Initiate file upload

POST /api/v1/data/{table}/file

Initiates a file upload session. The file API allows circumventing the batch upload API payload size limit by allowing upload of large data sets. The file API accepts data in gzip compressed ndjson format, stored into a file.

File must be a gzip compressed ndjson, normal JSON arrays are not accepted.

The data file is uploaded to AWS S3 and processed asynchronously. The file must be compressed with gzip before uploading to reduce the size of the transferred data.

The file API is not a single API, but requires a minimum of three calls (per table). The sequence is as follows:

  1. Initiate the file upload process
  2. Upload compressed ndjson file to S3, using the signed URL
  3. Trigger file processing
  4. (Optional) Poll the file processing status
Loading diagram...

You can find the bash implementation of the flow at our tools repository. See the upload-file.sh script.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
Successful responses
ResponseTypeDescription
200 OKobjectThe details to execute the S3 upload
Response format
{
// The uuid of the file upload session. Required.
"id": string,
// The presigned S3 url where to push the data. Required.
"url": string,
// The http method used for uploading to S3. Required.
"method": string,
// Defines when the presigned upload link expires. Required.
"expires": string
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X POST \
  https://your-env-name.api.aito.ai/api/v1/data/products/file \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "id": "7cbdb49f-3c12-4085-af91-372f5812eceb",
  "url": "https://aitoai-customer-uploads.s3.eu-west-1.amazonaws.com/your-env-name/products/7cbdb49f-3c12-4085-af91-372f5812eceb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20190515T100150Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1199&X-Amz-Credential=AKIAI5RFK3NF3YVDPC6A%2F20190515%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=ab6c7059b9716d5036edd9faa679e9ee0376c8da778b9783ca6dd74c5665ea11",
  "method": "PUT",
  "expires": "2019-05-15T10:21:49"
}

Trigger file processing

POST /api/v1/data/{table}/file/{uuid}

Starts the processing of a previously uploaded file.

Note: This operation is part of the file upload sequence. If you want to read how to execute a full file upload flow, see Initiate file upload documentation.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
uuidrequiredstringThe assigned id of the operation
Successful responses
ResponseTypeDescription
200 OKobjectProcessing started status
Response format
{
// The id of the operation. Should match the one in the url // parameter. Required.
"id": string,
// Textual description of the job. Required.
"status": string
}

Example request

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X POST \
  https://your-env-name.api.aito.ai/api/v1/data/products/file/6f0dc59c-0b6a-404e-a97f-b5a6990bbedf \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

{
  "id": "6f0dc59c-0b6a-404e-a97f-b5a6990bbedf",
  "status": "started"
}

Get file processing status

GET /api/v1/data/{table}/file/{uuid}

Returns the file upload progress, as well as the last failing rows (max 50).

The response is probabilistic and might not contain the very last result, since the status update is asynchronous, and the upload happens in multiple parallel streams. The response, however, will give an idea of approximate progress.

Note: This operation is part of the file upload sequence. If you want to read how to execute a full file upload flow, see Initiate file upload documentation.

Parameters
NameTypeDescription
tablerequiredstringThe name of the table to add data to
uuidrequiredstringThe assigned id of the operation
Successful responses
ResponseTypeDescription
200 OKobjectThe file processing status
Response format
{
"status": {
// Total duration of the file processing elapsed. Required.
"totalDurationMs": number,
// Total duration of the file processing elapsed as human // readable units. Required.
"totalDuration": string,
// Throughput of lines in human readable units.
"throughput": string,
// When the file processing was started. Required.
"startedAt": string,
// When the file processing was finished. Required.
"finishedAt": string,
// Is the job finished or not. Required.
"finished": boolean,
// The number of lines completed so far. Required.
"completedCount": integer,
// Any object which is valid according to the database schema. // Required.
"lastSuccessfulElement": UserDefinedObject
},
"errors": {
// Human consumable description. Required.
"message": string,
// Array of failing elements. The number of returned elements // is restricted.
"rows": [UserDefinedObject, ...]
}
}

Request during processing

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X GET \
  https://your-env-name.api.aito.ai/api/v1/data/products/file/89c1c1b6-1eaa-4da5-b9ee-e4f3d64bb8c2 \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

The example shows what the response looks while data processing is still in progress.

{
  "status": {
    "finished": false,
    "completedCount": 0,
    "startedAt": "20190515T100151.540Z",
    "throughput": "0/s"
  },
  "errors": { "message": "Last 0 failing rows", "rows": null }
}

Request after processing

This request sample is not directly copy-pasteable. Your own Aito environment is required.

curl -X GET \
  https://your-env-name.api.aito.ai/api/v1/data/products/file/e58a47fe-992d-4035-ba18-43de627f56db \
  -H 'x-api-key: YOUR_READ_WRITE_API_KEY'

Response

The example shows what the response looks after data processing has been successfully done.

{
  "status": {
    "totalDurationMs": 1485,
    "finished": true,
    "completedCount": 3,
    "lastSuccessfulElement": {
      "id": 3,
      "name": "Samsung Galaxy S9",
      "price": 698.2,
      "description": "The Camera. Reimagined."
    },
    "totalDuration": "1 second and 485 milliseconds",
    "startedAt": "20190515T100152.547Z",
    "finishedAt": "20190515T100154.032Z",
    "throughput": "2.02/s"
  },
  "errors": { "message": "Last 0 failing rows", "rows": null }
}

API types

Data types which are not part of the query language.

BooleanType

Boolean column type.

When column is a boolean, the only accepted values are true and false.

Format
{
// Type of the column. Required.
"type": string,
// When true, `null` values are allowed. // Default: true
"nullable": boolean
}

Example

{ "type": "Boolean" }

ColumnType

Type of the column.

Describes an individual field (or column), the type, and information to help Aito preprocess your data. For example what language a textual data contains.

Format

Examples

{ "type": "Int", "nullable": false }
{ "type": "String", "nullable": false }
{ "type": "Decimal", "nullable": false }
{ "type": "Text", "nullable": false, "analyzer": "English" }

DecimalType

Double-precision floating-point number.

Format
{
// Type of the column. Required.
"type": string,
// When true, `null` values are allowed. // Default: true
"nullable": boolean
}

Example

{ "type": "Decimal", "nullable": false }

IntType

Integer column type.

Format
{
// Type of the column. Required.
"type": string,
// When true, `null` values are allowed. // Default: true
"nullable": boolean
}

Example

{ "type": "Int" }

StringType

String column type.

The string data type is a primitive version of the Text type. The value is turned into a single feature. For example "lazy black cat" becomes 1 feature: "lazy black cat".

Format
{
// Type of the column. Required.
"type": string,
// When true, `null` values are allowed. // Default: true
"nullable": boolean
}

Example

{ "type": "String", "nullable": false }

TextType

Text column type.

The text data type allows smarter textual analysis. Aito extracts features of the given text contents with the configurable analyzer.

Supported analyzers:

  • "Whitespace" Extracts features by white space splitting.

    "lazy black cat" would be turned into 3 features: "lazy", "black", "cat".

  • "English" Extracts features by English stemming.

    "aito database" would be turned into 2 features: "aito", "databas".

  • "Finnish"

  • "Swedish"

  • "German"

Format
{
// Type of the column. Required.
"type": string,
// The analyzer to use for feature extraction.
"analyzer": string,
// When true, `null` values are allowed. // Default: true
"nullable": boolean
}

Example

{ "type": "Text", "analyzer": "English", "nullable": false }

UserDefinedObject

Any object which is valid according to the database schema.

The contents of the object depends on the data inserted into the database. If for example you have a products table which has fields name and price, your object could look like:

{ "name": "My product", "price": 172.19 }
Format
object

Example

{ "name": "My product", "price": 172.19 }

UserDefinedTableSchema

Any schema which is a valid Aito table schema.

Table schema describes the structure of the table in a formal language. The schema describes all fields (or columns), data types of the fields, and information to help Aito preprocess your data. For example what language a textual data contains.

The contents of the schema depends on the data that will be inserted into the database.

Format
{
// Type of the database schema item. Currently only 'table' is // accepted.
"type": string,
// Table columns. Each key-value pair is a column name and the // column type.
"columns": {
// Type of the column.
"<yourColumnName>": ColumnType
}
}

Example

{
  "type": "table",
  "columns": {
    "id": { "type": "Int", "nullable": false },
    "name": { "type": "String", "nullable": false },
    "price": { "type": "Decimal", "nullable": false },
    "description": { "type": "Text", "nullable": false, "analyzer": "English" }
  }
}

Query language

The reference documentation for Aito query language.

Common concepts

Features

To make better analysis of the data, Aito splits fields into features under the hood. How the featurisation is done, depends on the field type. For example the Text type supports an "analyzer" option which allows you to control how a text field is splitted into features.

Some queries, for example Relate, return the features instead of the actual values of the field.

Exclusiveness

Exclusiveness is an option in predictions. In summary, it describes whether the predicted field can have multiple values at the same time or not.

Understanding the concept is easiest through an example. If we were predicting tags for a product, we would want to set "exclusiveness": false, because a product can have multiple tags. A product could be described with the following tags:

Venn diagram of tags

However if we were predicting the user, who would most likely purchase a product, we would want to use "exclusiveness": true (default behavior) because the value can only be one user at a time.

Venn diagram of users

$p vs $lift

If we were trying to find a customer, who is best characterized by a message, we'd need to understand the difference between $p and $lift. To make the difference clear, consider the following situation:

  • Alice messages often, but she doesn't mention iPhone often
  • Bob messages rarely, but only about iPhones

Querying users by $p quite likely finds Alice, because she may be overall the more likely person to mention "iPhone". Querying users by $lift, on the other hand will very certainly find Bob, because $lift describes that how characteristic the feature "iPhone" is for the user.

A more mathematical and technical description for the phenomenon is the following:

Aito uses Bayesian probability inference to estimate p(Xcontext)\footnotesize p(X|context) so that p(Xcontext)=p(X)lift(Xcontext)\footnotesize p(X|context) = p(X) * lift(X|context) where the probability lift component lift(Xcontext)=p(contextX)/p(context)\footnotesize lift(X|context) = p(context|X)/p(context)

The probability lift component describes that how much more likely X is true in the specified context, when compared to average.

In Aito query syntax: $p stands for the p(Xcontext)\footnotesize p(X|context), while $lift stands for the lift(Xcontext)\footnotesize lift(X|context) component.

Text operators

Useful for creating conditional queries with text fields.

$match

Operator to check if a textual field fuzzy matches a given string.

Case insensitive. The matched text is split to tokens with the analyzer specified for the field in schema. For example { "$match": "great programmers" } will match strings "Bob is the greatest programmer!", and "Programmers are having great fun" if the field is properly analyzed with the English analyzer.

Format
{
// String to match the field with.
"$match": string
}

Examples

{ "$match": "coffee" }
{
  "from": "products",
  "where": {
    "name": { "$match": "coffee" }
  }
}

$startsWith

Operator to check if a textual field starts with a given string. Case sensitive.

Format
{
// The string to search for.
"$startsWith": string
}

Examples

{ "$startsWith": "Cucumber" }
{
  "from": "products",
  "where": {
    "name": { "$startsWith": "Cucumber" }
  }
}

Comparison operators

Useful for creating conditional queries.

$gt

Operator to check if a field is greater than a given value.

Format
{
// The given value.
"$gt": number
}

Examples

{ "$gt": 8 }
{ "$gt": 231.1 }
{
  "from": "products",
  "where": {
    "price": { "$gt": 2.14 }
  }
}

$gte

Operator to check if a field is greater than or equal to a given value.

Format
{
// The given value.
"$gte": number
}

Examples

{ "$gte": -2 }
{ "$gte": 0 }
{
  "from": "products",
  "where": {
    "price": { "$gte": 2 }
  }
}

$lt

Operator to check if a field is less than a given value.

Format
{
// The given value.
"$lt": number
}

Examples

{ "$lt": 4 }
{ "$lt": -12.1 }
{
  "from": "products",
  "where": {
    "price": { "$lt": 1.24 }
  }
}

$lte

Operator to check if a field is less than or equal to a given value.

Format
{
// The given value.
"$lte": number
}

Examples

{ "$lte": 8 }
{ "$lte": 0 }
{
  "from": "products",
  "where": {
    "price": { "$lte": 1 }
  }
}

$has

Has operation checks whether the field has the specified feature.

$has is a low level operation, that operates at the feature level. The features can differ significantly from the original data, specifically in case of text, when analyzers are used.

For example if you have field called content with the text "programmers and horses", the field would have features 'programmer' and 'hors', which are stems by the English analyzer.

Format
{
// The feature expected to be found.
"$has":
integer
or
number
or
boolean
or
null
or
string
}

Examples

{ "$has": "coffe" }
{
  "from": "products",
  "where": {
    "name": { "$has": "coffe" }
  }
}

$defined

Operator to select rows based on if an nullable field has been defined or not.

Format
{
// Defines whether a nullable field should be defined or not.
"$defined": boolean
}

Example

{ "$defined": true }

$exists

An operator to get features of given field(s).

Format
{
// PropositionSet expression is used to describe a collection // of propositions.
"$exists": PropositionSet
}

Examples

{
  "$exists": ["query", "product.tags"]
}
{
  "from": "impressions",
  "where": {
    "$on": [
      {
        "$exists": ["query", "customer.tags"]
      },
      { "click": true }
    ]
  },
  "relate": ["product.title", "product.tags"]
}

Logical operators

Useful for combining multiple conditions in conditional queries.

$and

Performs a logical and operation on the given array containing two or more Propositions.

Format
{
// Array of propositions to `and`.
"$and": [Proposition, Proposition, ...]
}

Examples

{
  "$and": [
    { "$gt": 10 },
    { "$lt": 20 }
  ]
}
{
  "from": "products",
  "where": {
    "price": {
      "$and": [
        { "$gt": 1.5 },
        { "$lt": 2.1 }
      ]
    }
  }
}

$or

Performs a logical or operation on the given array containing two or more Propositions.

Format
{
// Array of propositions to `or`.
"$or": [Proposition, Proposition, ...]
}

Examples

{
  "$or": [
    { "$lt": 0 },
    { "$gt": 20 }
  ]
}
{
  "from": "products",
  "where": {
    "price": {
      "$or": [
        { "$lt": 0.9 },
        { "$gt": 2.1 }
      ]
    }
  }
}

$not

Performs a logical not operation on the given Proposition.

Format
{
// Proposition expression describes a fact, or a statement.
"$not": Proposition
}

Examples

{
  "$not": { "$lt": 0 }
}
{
  "from": "products",
  "where": {
    "price": {
      "$not": { "$lt": 1.1 }
    }
  }
}

Sort operators

Can be used in "orderBy" clause to declare the sorting order of the result.

$asc

Sort returned hits in ascending order (A-Z) based on the given attribute or custom scoring function.

Format
{
// Value expression resolves to a primitive like int or json, // score, probability or.
"$asc": Value
}

Examples

{ "$asc": "price" }
{ "$asc": "product.price" }
{
  "$asc": {
    "$multiply": ["product.price", "$p"]
  }
}

$asc(Relate)

Sort returned hits in ascending order (A-Z) based on the given attribute (or column).

Format
{
"$asc": string
}

Example

{ "$asc": "price" }

$desc

Sort returned hits in descending order (Z-A) based on the given attribute or custom scoring function.

Format
{
// Value expression resolves to a primitive like int or json, // score, probability or.
"$desc": Value
}

Examples

{ "$desc": "price" }
{ "$desc": "product.price" }
{
  "$desc": {
    "$multiply": ["product.price", "$p"]
  }
}

$desc(Relate)

Sort returned hits in descending (Z-A) order based on the given attribute (or column).

Format
{
"$desc": string
}

Example

{ "$desc": "price" }

Arithmetic operators

Can be used in conditional queries or scoring in "orderBy" clauses.

$mod

Operator to check if the value of a field divided by a divisor has the specified remainder.

In other words perform a modulo operation. This operator supports object or array form. Note that the field will be converted to an integer (effectively a math floor) before the modulo operation.

Format
{
"$mod":
}

Examples

{
  "$mod": [2, 0]
}
{
  "$mod": { "divisor": 2, "remainder": 0 }
}
{
  "from": "products",
  "where": {
    "price": {
      "$mod": { "divisor": 2, "remainder": 0 }
    }
  }
}

$multiply

Multiplication operation of given items.

Format
{
"$multiply": [Score, ...]
}

Example

{
  "$multiply": ["price", 2]
}

$pow

Exponentiation operation. First item raised to the power of the second.

Format
{
"$pow": [Score, Score]
}

Example

{
  "$pow": ["width", 2]
}

$sum

Calculates sum of given items.

Format
{
"$sum": [Score, ...]
}

Example

{
  "$sum": ["priceNet", "priceVat"]
}

Advanced operators

More advanced operators which can improve query results in certain situations.

$atomic

Transforms a statement into a 'black box' proposition.

This prevents Aito from analyzing the proposition and using its parts separately in the statistical reasoning.

In practice the difference between normal 'white box' expressions, and the $atomic's black box expressions is: that the atomic expressions have a smaller bias, but a higher measurement error.

Consider the following example:

{
  "tags": "pen",
  "price": { "$gte": 200 } }
}

During the statistical reasoning: Aito may recognize that pens are often sold, and that over 200€ product purchases are somewhat common. As a result, Aito might assume the over 200€ pen to be a popular product.

Now, consider the expression:

{
  "$atomic": {
    "tags": "pen",
    "price": { "$gte" : 200 }
  }
}

The results of this expression will depend of the amount of data. If there are no over 200€ pens in the data: Aito will make no assumptions of the proposition's effect. On the other hand, if you have the data: Aito will recognize correctly, that the over 200€ pens are bought extremely rarely.

Format
{
// Proposition expression describes a fact, or a statement.
"$atomic": Proposition
}

Example

{
  "$atomic": {
    "tags": "pen",
    "price": { "$gte": 200 }
  }
}

$context

Provides ability to access the fields of the table specified in "from", instead of fields of the table in "get".

Format
{
// Proposition expression describes a fact, or a statement.
"$context": Proposition
}

Examples

{
  "$context": { "click": true }
}
{
  "from": "impressions",
  "where": { "customerEmail": "john.doe@aito.ai", "query": "laptop" },
  "get": "product",
  "orderBy": {
    "$p": {
      "$context": { "click": true }
    }
  }
}

$hit

Provides ability to access the fields of the hit.

Format
{
// Score expression resolves to a numeric score value or // probability.
"$hit": AdvancedScore
}

Example

{ "$hit": "price" }

$on

$on operator is used to define conditional propositions or hard filters.

This is useful when you have limited amount of data and the condition would help to limit the context and provide better results. This can be done by providing a list containing of two items, the first object (or "prop") is the hypothesis and the second object (or "on") is the conditional.

In Aito the where clause contains propositions which aren't hard filters. Instead, Aito will turn all the propositions into features (the user's ID, every word in a text field, etc.). There are many of these and they are not statistically independent. Aito picks a subset of these features that are the best predictors of the field that is to be predicted. So what goes into the "where" is a description of the situation you're in and Aito tells you what you should expect to find if you look in a field. But the description is not taken at face value, Aito will ignore parts of it if it doesn't help the prediction.

However, there is another way to achieve this: the "$on" proposition. It is modeled after conditional probability. It is divided into two parts, the normal "where" parts and the conditional part ("hard filters"). The "$on" parameters explained:

{
  "from": "...",
  "where": {
    "$on": [
      {
        "message": "hello, world",
        "something": true,
        // other things you put in your "where" clause
      },
      {
        // The subset of data that exactly matches these conditions
        "userId": 42,
        "day": "monday"
      }
    ]
  },
  "predict": "..."
}

The $on can also be combined with normal query. If the $on condition is too strong, you could move parts of the filtering back to the where clause:

{
  "from": "...",
  "where": {
    "$on": [
      {
        "message": "hello, world",
        "something": true,
        // other things you put in your "where" clause
      },
      {
        // The subset of data that exactly matches these conditions
        "day": "monday"
      }
    ],
    "user_id": 42
  },
  "predict": "..."
}
Format
{
"$on":
{
// Proposition expression describes a fact, or a statement.
"prop": Proposition,
// Proposition expression describes a fact, or a statement.
}
or
}

Examples

{
  "$on": {
    "prop": { "click": true },
    "on": { "user.tags": "nyc" }
  }
}
{
  "$on": [
    { "click": true },
    { "user.tags": "nyc" }
  ]
}

Scoring operators

Can be used in "orderBy" clause to sort or create an advanced scoring algorithm.

$lift

"$lift" can be used in Generic query to get most likely values based on lifts of features with regard to other features.

As an example, let's say we had a messages table which has a user link to users table.

{
  "from": "messages",
  "where": { "message": { "$match": "dog" } },
  "get": "user",
  "orderBy": "$lift"
}

This query would find the person who is talking most about dogs, relative to the amount of the messages they send.

See also $p and $lift.

Format
string

Example

"$lift"

$p

"$p" can be used in Generic query to get the most probable values. When used this way, it works like the Match query.

As an example, let's say we had a messages table which has a user link to users table.

{
  "from": "messages",
  "where": { "message": { "$match": "dog" } },
  "get": "user",
  "orderBy": "$p"
}

This query would find the person who would most probably mention dogs overall. See also $p and $lift.

Format
string

Example

"$p"

$similarity

"$similarity" can be used in Generic query to get most similar rows based on the contents of the "where" clause.

Consider the following example. It will return all the products, that contain 'iphone' in the title. It also sorts the results by their similarity to the 'iphone' and highlight the 'iphone' term in the product title field.

{
  "from": "product",
  "where": { "title": { "$match": "iphone" } },
  "get": "message",
  "orderBy": "$similarity",
  "select": ["title", "$highlight"]
}
Format
string

Example

"$similarity"

$lift object

Same as plain $lift, but allows you to customize a proposition for the lift calculation.

Format
{
// PropositionSet expression is used to describe a collection // of propositions.
"$lift": PropositionSet
}

Example

{
  "$lift": {
    "$context": { "click": true }
  }
}

$p object

Same as plain $p, but allows you to customize a proposition for the probability calculation.

Format
{
// PropositionSet expression is used to describe a collection // of propositions.
}

Example

{
  "$p": {
    "$context": { "click": true }
  }
}

$similarity object

Same as plain $similarity, but allows you to customize a proposition for the similarity calculation. The plain $similarity without arguments will base the similarity on the "where" clause contents, whereas this $similarity object will use the given proposition.

Format
{
// Proposition expression describes a fact, or a statement.
"$similarity": Proposition
}

Example

{
  "$similarity": { "message": "Recommend me a premium laptop" }
}

Built-in attributes

Can be used in "select" clause.

$index

$index is a built-in variable which indicates the insertion index of a row. It can be used together with $mod to select parts of a table. It's useful for example in Evaluate query for selecting training or test data.

Format
string

Example

"$index"

$lift

"$lift" can be used in Generic query to get most likely values based on lifts of features with regard to other features.

As an example, let's say we had a messages table which has a user link to users table.

{
  "from": "messages",
  "where": { "message": { "$match": "dog" } },
  "get": "user",
  "orderBy": "$lift"
}

This query would find the person who is talking most about dogs, relative to the amount of the messages they send.

See also $p and $lift.

Format
string

Example

"$lift"

$p

"$p" can be used in Generic query to get the most probable values. When used this way, it works like the Match query.

As an example, let's say we had a messages table which has a user link to users table.

{
  "from": "messages",
  "where": { "message": { "$match": "dog" } },
  "get": "user",
  "orderBy": "$p"
}

This query would find the person who would most probably mention dogs overall. See also $p and $lift.

Format
string

Example

"$p"

$why

When selecting $why, Aito opens up why a certain result was predicted. Explanation contains 3 different factors, which are explained below.

The three different factors are for an estimate of form:

p(xiA,B,C)p(x_i | A, B, C)

"baseP"

The base probability.

p(X)p(X)

"normalizer"

The normalizer is only used, when exclusiveness is on. In this case, it is assumed that only one feature can be true at the same time, and that one feature will be true. In practice, exclusiveness enforces the probabilities of alternative features to sum to 1.0.

The normalizer of form:

1sum((p(X0)+p(X1)+...))\dfrac{1}{sum((p(X_0) + p(X_1) + ...))}

Probability lifts. For example: the lift may say a product is clicked with 2.3x likelihood (or 130% higher likelihood), when it has 5 stars.

A probability lift is of form:

p(AX)p(A)\dfrac{p(A | X)}{p(A)}
Format
string

Examples

"$why"
{
  "select": ["$why"]
}
{
  "from": "impressions",
  "where": { "session.user": "veronica", "product.id": "6409100046286" },
  "select": ["$why"],
  "predict": "purchase"
}

Other types

All other API types.

AdvancedScore

Score expression resolves to a numeric score value or probability. All scores can be used in both highlights ($highlight) and explanations ($why).

Format

Examples

2
"product.price"
"$p"
"$similarity"
{
  "$multiply": ["$p", "price"]
}

ArithmeticOperation

Arithmetic operation.

Format
number
or

Examples

10
{
  "$multiply": ["$p", "price"]
}
{
  "$pow": ["width", 2]
}
{
  "$multiply": [
    "quantity",
    {
      "$multiply": ["$p", "price"]
    }
  ]
}

ColumnName

Name of a column in a table. Links are supported.

Format
string

Examples

"product.id"
"product.price"
"age"

DocumentProposition

DocumentProposition expresses statements about a document.

For example the expression

{
  "tags": "laptop",
  "price": { "$lt": 500 }
}

describes a product, where the product is tagged as a laptop, and its price is under 500

Format
object

Examples

{ "click": true }
{ "query": "laptop" }
{
  "product.tags": { "$match": "laptop" },
  "click": true
}

EvaluateOperation

Operation to be evaluated.

Format
object

Example

{
  "where": ["name"],
  "predict": "tags"
}

From

From expression declares the examined table.

Format
string

Examples

"products"
"customers"
"messages"

Get

Get expression defines what items are returned as query results.

By default, the hits are from the table defined in "from" clause. In some cases, you may want to declare propositions like 'query is laptop' in impression table, while returning results from the separate products table, based on click likelihood. In this case, you may have query such as

{
  "from": "impressions",
  "where": { "query": "laptop" },
  "get": "product",
  "orderBy": {
    "$p": {
      "$context": { "click": true }
    }
  }
}

The "get" expression takes a field name as a parameter. If the field is link, the returned results are from the linked table. If the field is not link, the field values are returned as results.

Normally, the result of a query consists of the field values that best fulfill the query conditions. Field analyzers extract features from text fields and the $feature property can be used to return features instead of complete field values. For instance, the following example demonstrates how to discover product tags which are likely to lead to sales

{
  "from": "impressions",
  "where": { "query": "cheap phone" },
  "get": "product.tags.$feature",
  "orderBy": {
    "$p": {
      "$context": { "click": true }
    }
  }
}

The $feature syntax also allows you to examine the values/features of a link field like it would be a regular field.

Format
string

Examples

"product"
"user"
"text.$feature"
"link.field"
"link.$feature"
"link.text.$feature"

Goal

Specifies a goal to maximize.

Results are ordered by the likelihood of the goal in descending order.

Format

Examples

{ "purchase": true }
{ "click": true }

Hits

Entries returned for a given query.

Format

Example

[
  {
    "$p": 0.16772371915637704,
    "category": "100",
    "id": "6410405060457",
    "name": "Pirkka bio cherry tomatoes 250g international 1st class",
    "price": 1.29,
    "tags": "fresh vegetable pirkka tomato"
  },
  {
    "$p": 0.16772371915637704,
    "category": "100",
    "id": "6410405093677",
    "name": "Pirkka iceberg salad Finland 100g 1st class",
    "price": 1.29,
    "tags": "fresh vegetable pirkka"
  }
]

ModArray

Array form of $mod operator.

Format
[integer, integer]

Example

{
  "$mod": [2, 0]
}

ModObject

Object form of $mod operator.

Format
{
// A number by which the field is to be divided.
"divisor": integer,
// The expected remainder of the modulo operation.
"remainder": integer
}

Example

{
  "$mod": { "divisor": 2, "remainder": 0 }
}

OrderBy

Declares the sorting order of the result by a field or by a user-defined score.

Format

Examples

"price"
"product.price"
{ "$asc": "product.price" }
{ "$desc": "product.price" }
{
  "$multiply": ["$p", "prices"]
}
{
  "$pow": ["product.width", 2]
}

PrimitiveProposition

PrimitiveProposition states a field's value.

It should always be used inside a field declaration of a document proposition. For example, in the proposition { "field": "value" } the string "value" is the primitive proposition.

Format
integer
or
number
or
boolean
or
null
or
string

Examples

4
3.1
false
null
"text"

Proposition

Proposition expression describes a fact, or a statement.

A proposition may for example say that 'customer 4 clicked item' or that 'the product price is under 100€ or that tags contain the term laptop'.

Format

Examples

{
  "customer": 4,
  "query": { "$match": "laptop" }
}
{
  "price": { "$lt": 100 }
}
{
  "tags": { "$match": "laptop" }
}

PropositionSet

PropositionSet expression is used to describe a collection of propositions. This collection of statements can be the alternative values in a field.

Format
string
or

Examples

"product.tags"
["query", "product", "tags"]

QueryOrderBy

To be clarified.

Format
string

Example

{ "$desc": "product.price" }

RelateOrderBy

To be clarified.

Format

Example

{ "$desc": "info.miTrue" }

Score

Score expression resolves to a numeric score value or probability. All scores can be used in both highlights ($highlight) and explanations ($why).

Format

Examples

2
"product.price"
{
  "$multiply": ["$p", "price"]
}

Selection

Describes the fields and/or built-in attributes to return.

Format
[
string
or
$why
or
,
...]

Examples

["user.name", "query", "product.title", "click"]
["$why"]

Value

Value expression resolves to a primitive like int or json, score, probability or individual feature.

Value expression can refer to any field in the table with expressions like "query" or "product.price". Value expression can refer to the narrowed document overall likelihood, for example "$p", after "get": "message", to refer the message's likelihood. Value can also refer to the likelihood of a proposition with expressions such as { "$p": { "tags": "cover" } } or { "$p": { "$context": "click" } } to refer to the context table's fields.

Format

Example

"product.id"

WhyFactor

Single $why factor.

See $why for more information.

Format

Example

{ "type": "baseP", "value": 0.28 }

WhyFactorBaseP

baseP factor of $why.

See $why for more information.

Format
{
// The factor identifier.
"type": string,
// The base probability value.
"value": number
}

Example

{ "type": "baseP", "value": 0.28 }

WhyFactorNormalizer

normalizer factor of $why.

See $why for more information.

Format
{
// The factor identifier.
"type": string,
"name": string,
"value": number
}

Example

{ "type": "normalizer", "name": "exclusiveness", "value": 1 }

relatedVariableLift factor of $why.

See $why for more information.

Format
{
// The factor identifier.
"type": string,
"variable": string,
"value": number
}

Example

{
  "type": "relatedVariableLift",
  "variable": "product.id:6409100046286",
  "value": 0.03993345456220958
}

WhyResponseItem

Response item when selecting $why.

See $why for more information about how to do the selection.

Format
{
// The wrapper object.
"$why": {
// The name of the of the object/link predicted.
"type": string,
// Contains the explanation factors of the prediction.
"factors": [WhyFactor, ...]
}
}

Example

{
  "$why": {
    "type": "product",
    "factors": [
      { "type": "baseP", "value": 0.5 },
      { "type": "normalizer", "name": "exclusiveness", "value": 1 },
      {
        "type": "relatedVariableLift",
        "variable": "product.id:6409100046286",
        "value": 0.03993345456220958
      }
    ]
  }
}