TinyBase logoTinyBase

Queries

A Queries object lets you create and track queries of the data in Store objects.

This is useful for creating a reactive view of data that is stored in physical tables: selecting columns, joining tables together, filtering rows, aggregating data, sorting it, and so on.

This provides a generalized query concept for Store data. If you just want to create and track metrics, indexes, or relationships between rows, you may prefer to use the dedicated Metrics, Indexes, and Relationships objects, which have simpler APIs.

Create a Queries object easily with the createQueries function. From there, you can add new query definitions (with the setQueryDefinition method), query the results (with the getResultTable method, the getResultRow method, the getResultCell method, and so on), and add listeners for when they change (with the addResultTableListener method, the addResultRowListener method, the addResultCellListener method, and so on).

Example

This example shows a very simple lifecycle of a Queries object: from creation, to adding definitions, getting their contents, and then registering and removing listeners for them.

import {createQueries, createStore} from 'tinybase';

const store = createStore()
  .setTable('pets', {
    fido: {species: 'dog', color: 'brown', ownerId: '1'},
    felix: {species: 'cat', color: 'black', ownerId: '2'},
    cujo: {species: 'dog', color: 'black', ownerId: '3'},
  })
  .setTable('species', {
    dog: {price: 5},
    cat: {price: 4},
    worm: {price: 1},
  })
  .setTable('owners', {
    '1': {name: 'Alice'},
    '2': {name: 'Bob'},
    '3': {name: 'Carol'},
  });

const queries = createQueries(store);

// A filtered table query:
queries.setQueryDefinition('blackPets', 'pets', ({select, where}) => {
  select('species');
  where('color', 'black');
});
console.log(queries.getResultTable('blackPets'));
// -> {felix: {species: 'cat'}, cujo: {species: 'dog'}}

// A joined table query:
queries.setQueryDefinition('petOwners', 'pets', ({select, join}) => {
  select('owners', 'name').as('owner');
  join('owners', 'ownerId');
});
console.log(queries.getResultTable('petOwners'));
// -> {fido: {owner: 'Alice'}, felix: {owner: 'Bob'}, cujo: {owner: 'Carol'}}

// A grouped query:
queries.setQueryDefinition(
  'colorPrice',
  'pets',
  ({select, join, group}) => {
    select('color');
    select('species', 'price');
    join('species', 'species');
    group('price', 'avg');
  },
);
console.log(queries.getResultTable('colorPrice'));
// -> {"1": {color: 'black', price: 4.5}, "0": {color: 'brown', price: 5}}
console.log(queries.getResultSortedRowIds('colorPrice', 'price', true));
// -> ["0", "1"]

const listenerId = queries.addResultTableListener('colorPrice', () => {
  console.log('Average prices per color changed');
  console.log(queries.getResultTable('colorPrice'));
  console.log(queries.getResultSortedRowIds('colorPrice', 'price', true));
});

store.setRow('pets', 'lowly', {species: 'worm', color: 'brown'});
// -> 'Average prices per color changed'
// -> {"0": {color: 'brown', price: 3}, "1": {color: 'black', price: 4.5}}
// -> ["1", "0"]

queries.delListener(listenerId);
queries.destroy();

See also

Since

v2.0.0

Getter methods

Result methods

Listener methods

Configuration methods

Iterator methods

Lifecycle methods

Development methods