Fetching data
Queries

Queries

Defining queries

Data in Triplit is organized into collections, so to define a query you must first specify which collection you want to query.

For example, if you want to query the users collection, you would write the following:

const query = client.query('users');

Selecting attributes

To specify which attributes you want to return, you can use the select method. This method accepts a list of attribute names for the collection as arguments.

const query = client.query('users').select(['id', 'name', 'email', 'dob']);
⚠️

Relationships are only partially supported in Triplit. Specifically you may filter data based on a relationship, however related data is not selectable. Full support for relationships is on the roadmap (opens in a new tab).

If the type you are selecting is a record, you may also select a specific attribute of the record by using dot notation. The result will be an object with just the selected keys.

const query = client
  .query('users')
  .select(['id', 'address.street', 'address.city']);
// {id: 'abc', address: {street: '123 Main St', city: 'New York'}}

If you do not call select on a query, all attributes are selected.

Filtering

To filter results based on conditions, you can use the where method. This method accepts a list of clauses as arguments. A clause is a tuple that takes the form [attribute, operator, value].

For example the following query will return all registered users.

const query = client
  .query('users')
  .select(['id', 'name', 'email', 'dob'])
  .where('is_registered', '=', true);

Clauses can be passed to where as a single clause or an array of clauses:

  • .where('is_registered', '=', true)
  • .where(['is_registered', '=', true])
  • .where([['is_registered', '=', true]])

If multiple clauses are provided, all clauses are joined with a logical AND. However, you may use or and and methods within the clause array to specify how clauses should be logically grouped and joined.

For example the following query will return all registered users who are either an admin or an owner.

import { or } from '@triplit/client';
 
const query = client
  .query('users')
  .select(['id', 'name', 'email', 'dob'])
  .where([
    [
      ['is_registered', '=', true],
      or([
        ['role', '=', 'admin'],
        ['role', '=', 'owner'],
      ]),
    ],
  ]);

You may use dot notation to filter by attirbutes of a record.

const query = client.query('users').where('address.city', '=', 'New York');

Operators

See the list of data types for more information on the operators that can be used in a where clause.

Order

To order the results of a query, you can use the order method. This method accepts a list of order clauses as an argument. An order clause is a tuple that takes the form [attribute, direction]. direction can be either ASC or DESC. Clauses are applied in the order they are provided.

For example the following query will return all users ordered by their creation date in descending order.

const query = client
  .query('users')
  .select(['id', 'name', 'email', 'dob'])
  .order('created_at', 'DESC');

Clauses can be passed to order as a single clause or an array of clauses:

  • .order('created_at', 'DESC')
  • .order(['created_at', 'DESC'])
  • .order([['created_at', 'DESC']])

You may use dot notation to order by attirbutes of a record.

const query = client.query('users').order('address.city', 'ASC');

Limit

Many times you will want to limit the number of results returned by a query. To do this, you can use the limit method.

For example, the following query will return the 10 most recently created users.

const query = client
  .query('users')
  .select(['id', 'name', 'email', 'dob'])
  .order('created_at', 'DESC')
  .limit(10);

As a convenience, Triplit also provides a method fetchOne to fetch just the first entity of a query result.

Variables

You may pass variables to a query by using the variables method. Variables are passed in as strings with $ prepended to the variable name.

For example, you may define a query that queries for restaurants that are open by cuisine:

const baseQuery = client.query('restaurants').where([
  ['is_open', '=', true],
  ['cuisine', '=', '$cuisine'],
]);
const openItalianRestaurantsQuery = baseQuery.variables({ cuisine: 'italian' });
const openMexicanRestaurantsQuery = baseQuery.variables({ cuisine: 'mexican' });

This can help prevent writing the same query multiple times with different values.

Certain variables are used internally by Triplit to aid with authorization and other features. These include:

  • $SESSION_USER_ID

Sync state

Triplit's client storage is split into two areas - an outbox for unsynced updates and a cache for synced updates. Sometimes you may want to indicate that to a user that data has not yet been saved to the server. To do this, you can use the syncStatus method. This method accepts a single sync state (pending, confirmed, all) as an argument.

For example, a messaging app could use two queries to build message sent indicators. In React:

const allMessagesQuery = client.query('messages').order(['createdAt', 'ASC']);
 
const pendingMessagesQuery = client
  .query('messages')
  .select(['id'])
  .syncStatus('pending');
 
function Messages() {
  const { results: allMessages } = useQuery(client, allMessagesQuery);
  const { results: pendingMessages } = useQuery(client, pendingMessagesQuery);
 
  return (
    <div>
      {allMessages.entries().map(([id, message]) => (
        <div>
          <p>{message.text}</p>
          <p>{pendingMessages.has(id) ? 'Sending...' : 'Sent'}</p>
        </div>
      ))}
    </div>
  );
}

Entity id

Setting entityId on your query will return exclusively the requested entity if it exists.

For example, the following query will return just the user with id abc, if it exists.

const query = client.query('users').entityId('abc');

You may also pass a DB variable to entityId.

const query = client.query('users').entityId('$userId');

As a convenience, Triplit also provides a method fetchById to fetch an entity by its id.