TypeDB 3.0 is live! Get started for free.

Insert query

In this guide, you’ll see how to insert data in a database using Studio, Console, or one of the drivers.

Understanding Insert queries

An Insert query is used to insert data into a TypeDB database. An insert clause is executed once per every result matched by the match clause of the same query. If the match clause is omitted, then the insert clause is executed exactly once. For a detailed explanation of the query see the Delete query page.

Sending Insert queries

Before you start, make sure you followed the instructions from the Defining schemas section. The easiest way to send an Insert query is to use Studio or Console:

Follow the Studio manual to connect to TypeDB and select a project folder. Then use the steps below:

  1. Use a drop-down list in the top toolbar to select a database.

  2. Switch to data session and write transaction types.

  3. Open a new tab and insert or type in an Insert query, for example:

    TypeQL Insert query
    insert
    $user1 isa user, has name "Alice", has email "alice@typedb.com";
    $user2 isa user, has name "Bob", has email "bob@typedb.com";
    $friendship (friend:$user1, friend: $user2) isa friendship;
    typeql
  4. Run the query by clicking the studio run Run Query button.

  5. Commit the changes by clicking the studio check Commit query button.

To send an Insert query programmatically, use drivers:

Follow the connection guide to connect the driver to a TypeDB server.

Open a data session to the selected database, open a write transaction, and use the transaction.query().insert() method:
let databases = DatabaseManager::new(driver);
let db = databases.get(DB_NAME)?;
{
    let session = Session::new(db, SessionType::Data)?;
    {
        let tx = session.transaction(TransactionType::Write)?;
        let insert_query = "
                            insert
                            $user1 isa user, has name 'Alice', has email 'alice@typedb.com';
                            $user2 isa user, has name 'Bob', has email 'bob@typedb.com';
                            $friendship (friend:$user1, friend: $user2) isa friendship;
                            ";
        let _ = tx.query().insert(insert_query)?;
        tx.commit().resolve()?;
    }
}
rust

Response interpretation

An Insert query returns all concepts that got inserted into the database as a stream of ConceptMap objects.

Let’s say we send the following Insert query with a match clause:

Match-insert query example
match
$u isa user, has name "Bob";
insert
$new-u isa user, has name "Charlie", has email "charlie@typedb.com";
$f($u,$new-u) isa friendship;
typeql

With the data inserted earlier on this page, we should match only one such user with the name "Bob". That leads to inserting one new user and one relevant relation. If multiple matches are made by the match clause, then the insert clause runs for each of them.

To check the number of times an Insert query gets executed, you can either check its response or send a read query with the same matching pattern.

The response is a Stream/Iterator of ConceptMap objects. One ConceptMap object for every execution of the insert clause. A ConceptMap object maps every variable from the insert clause of the query to a concept in a database.

The easiest way to check the response for the query is to use a TypeDB client: Studio or Console. Send the above match-insert query the same way as the previous query.

Both Studio and Console should produce similar results:

{
    $bob iid 0x826e80018000000000000004 isa user;
    $f iid 0x847080017fffffffffffffff (friend: iid 0x826e80018000000000000002, friend: iid 0x826e80018000000000000004) isa friendship;
    $alice iid 0x826e80018000000000000002 isa user;
}
typeql

To process the response of an Insert query programmatically, you need to collect the response and iterate through it with a TypeDB driver. The number of iterations is equal to the number of the insert clause executions and every iteration returns a ConceptMap object with inserted data.

Let’s see an example of programmatically processing the response, where we commit the transaction only if the number of inserts meets our expectation.

Process Insert query response

Follow the connection guide to connect the driver to a TypeDB server.

Open a data session to the selected database, open a write transaction, and use the transaction.query().insert() method:
let databases = DatabaseManager::new(driver);
let db = databases.get(DB_NAME)?;
{
    let session = Session::new(db, SessionType::Data)?;
    {
        let tx = session.transaction(TransactionType::Write)?;
        let match_insert_query = "
                                match
                                $u isa user, has name 'Bob';
                                insert
                                $new-u isa user, has name 'Charlie', has email 'charlie@typedb.com';
                                $f($u,$new-u) isa friendship;
                                ";
        let response_count = tx.query().insert(match_insert_query)?.count();
        if response_count == 1 {
            tx.commit().resolve()?;
        } else {
            tx.force_close();
        }
    }
}
rust

Estimation with a read query

You can estimate the number of inserts made by an Insert query with a match clause by running a preliminary Fetch or Get query with the same match clause in the same transaction. Read queries can be used in a write transaction, and write transactions are snapshoted. Snapshot isolation prevents other transactions from influencing the results.

The most direct approach is to send an aggregated Get query to count the number of matches.

Checking the number of matched results
match $bob isa user, has email "bob@typedb.com";
get; count;
typeql

The response should be a single number.

Learn more

More about an Insert query

Learn more about Insert queries in TypeQL: syntax, behavior, and query examples.

Learn how to delete data from a database.

Check out the Writing data section of TypeDB Academy.