Implementing ActiveQL
EntityManager

Entity Manager

The datastore encapsulates the actual database used for reading and writing data. It is important to understand that ActiveQL uses entities for this. As long as you don't need access to the specfic datastore implementation (e.g. writing SQL queries) you should rely on the EntityManager for entity CRUD operations.

const Car = runtime.entityManager('Car'); // EntityManager<Car>
const cars = await Car.findAll(); // Car[]
Entity Manager MethodDescription
newItem():Treturns a new empty entity item
findById( id:string ):Promise<T>returns entity item with the given id throws an error when no such entity item exists
findByIds( ids:string[] ):Promise<T[]>returns all entity items with one of the given ids; returns an empty [] when no such entity items exists
findByAttribute( attrValue:{[name:string]:any} ):Promise<T[]>returns all entity items with the attribute values ; returns an empty [] when no such entity items exists
findOneByAttribute( attrValue:{[name:string]:any} ):Promise<T|undefined>returns one (or the first) entity item with the attribute values
findAll( sort?:Sort, paging?:Paging):Promise<T[]>returns all entity items
findByFilter( filter:any, sort?:Sort, paging?:Paging ):Promise<T[]>returns all entity items that fullfill the filter

Filter

You can use a filter to find sepecific entity items. Please be aware the filter structure and behavior depends on the specific datastore implementation. The following overview is true for the PgDataStore implementation (using a Postgres database). The default implementation, using NeDB (which is not recommended for production but rather test and development) behaves quite similar. Other datastore implementations should also lean to this syntax.

StringFilter
FilterTypeDescriptionNeDB special
isstringequal this value, case-sensitive can be be applied (default: true)
isNotstringdoes not equal this value, case-sensitive can be be applied (default: true)
instring[]value is in the list of strings, case-sensitive
notInstring[]value is not in the list of strings, case-sensitivewill not include null values
containsstringcontains this value, case-sensitive can be be applied (default: true)
notContainsstringdoes not contains this value, case-sensitive can be be applied (default: true)
beginsWithstringbegins with this value, case-sensitive can be be applied (default: true)
endsWithstringends with this value, case-sensitive can be be applied (default: true)
regexstringvalue matches this regex, case-sensitive can be be applied (default: true)
isNullbooleanvalue either null or non-null value
caseSensitivebooleandefault:true, can be applied to all operators except in and notIn
entity:
  Driver: 
    attributes: 
      firstname: String
      lastname: String!
    seeds: 
      items: 
        - firstname: Thomas
          lastname: Thompson
        - firstname: Michael
          lastname: Myers
        - firstname: Michael
          lastname: Majors
        - firstname: Samual
          lastname: Thompson
        - lastname: Smith
filter = { firstname: { in: ['Thomas', 'Michael'] } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //3
filter = { firstname: { notIn: ['Thomas', 'Michael'] } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //1
filter = { firstname: { contains: 'm' } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //2
filter = { firstname: { contains: 'm', caseSensitive: false  } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //4
filter = { firstname: { notContains: 'm', caseSensitive: false } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //0 (null is not considerd)
filter = { firstname: { beginsWith: 't' } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //0
filter = { firstname: { beginsWith: 't', caseSensitive: false  } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //1
filter = { firstname: { endsWith: 'l' } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //3
filter = { firstname: { regex: 'h(.*)a' } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //3
filter = { firstname: { isNull: true } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //1
filter = { firstname: { endsWith: 'l' }, lastname: { beginsWith: 't', caseSensitive: false } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); //1
IntFilter | FloatFilter
FilterTypeDescriptionNeDB special
isnumberequal this value
isNotnumberdoes not equal this value; including null values
lowerOrEqualnumberlower or equal equal this value; not including null values
lowernumberlower than this value; not including null values
greaterOrEqualnumbergreater or equal this value
greaternumbergreater than this value
isInnumber[]included in this list of values
notInnumber[]not included in this list of values; not including null valuesincluding null values
betweennumber[]greater or equal than the first and lower than the last number of this list of values
isNullbooleaneither null or non-null value
entity:
  Car: 
    attributes: 
      brand: String!
      power: Int
    seeds: 
      items: 
        - brand: Porsche
          power: 220
        - brand: Porsche
          power: 230
        - brand: Mercedes
          power: 190
        - brand: BMW
          power: 205
        - brand: Porsche
          power: 205
        - brand: Mercedes
filter = { power: { is: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 2
filter = { power: { isNot: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 4
filter = { power: { lowerOrEqual: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 3
filter = { power: { lower: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 1
filter = { power: { greaterOrEqual: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 4
filter = { power: { greater: 205 } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 2
filter = { power: { isIn: [190, 205, 300] } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 3
filter = { power: { notIn: [190, 205, 300] } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 2
filter = { power: { between: [190, 230] } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 4
filter = { power: { isNull: true } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 1
filter = { power: { isNull: false } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 5
BooleanFilter
FilterTypeDescription
isbooleanvalue is true or false
isNotnumbervalue is not true or false; including null values
isNullbooleaneither null or non-null value
entity:
  Car: 
    attributes: 
      brand: String!
      available: Boolean
    seeds: 
      items: 
        - brand: Porsche
          available: true
        - brand: Porsche
          available: false
        - brand: Mercedes
          available: true
        - brand: BMW
filter = { available: { is: true } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 2
filter = { available: { is: false } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 1
filter = { available: { isNot: true } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 2
filter = { available: { isNot: false } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 3
filter = { available: { isNull: true } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 1
filter = { available: { isNull: false } };
cars = await runtime.entityManager('Car').findByFilter( filter ); // 3
DateFilter | DateTimeFilter
FilterTypeDescription
isstring | Dateequal this value
isNotstring | Datedoes not equal this value; including null values
beforeOrEqualstring | Datebefore or equal equal this value; not including null values
beforestring | Datebefore this value; not including null values
afterOrEqualstring | Dateafter or equal this value
afterstring | Dateafter this value
isIn(string | Date)[]included in this list of values
notIn(string | Date)[]not included in this list of values; not including null values
between(string | Date)[]after or equal the first and before the last date of this list of values
isNullbooleaneither null or non-null value
entity:
  Driver: 
    attributes: 
      firstname: String!
      birthdate: Date
    seeds: 
      items: 
        - firstname: Thomas
          birthdate: 1990-09-09
        - firstname: Michael
          birthdate: 1998-08-08
        - firstname: Michael
          birthdate: 1990-09-09
        - firstname: Samual
          birthdate: 2000-02-02
        - lastname: Smith
filter = { birthdate: { is: "1990-09-09" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 2
filter = { birthdate: { isNot: "1990-09-09" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 3
filter = { birthdate: { beforeOrEqual: "1998-08-08" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 3
filter = { birthdate: { before: "1998-08-08" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 2
filter = { birthdate: { afterOrEqual: "1990-09-09" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 4
filter = { birthdate: { after: "1990-09-09" } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 2
filter = { birthdate: { isIn: ["1990-09-09", "1998-08-08", "2001-02-01"] } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 3
filter = { birthdate: { notIn: ["1990-09-09", "1998-08-08", "2001-02-01"] } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 2
filter = { birthdate: { between: ["1990-09-09", "1998-08-08"] } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 2
filter = { birthdate: { isNull: true } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 1
filter = { birthdate: { isNull: false } };
drivers = await runtime.entityManager('Driver').findByFilter( filter ); // 4

Sort

Some of the finder methods accept a sort parameter which influences the sorting of the entity items. Since every sorting might affect the performance of the datastore you should only use it when necessary.

Sort propertyTypeDescription
fieldstringthe field used for sorting
directionASC | DESCthe sort direction, ascending or descending
const Car = runtime.entityManager('Car'); 
const cars = await Car.findAll( {field: 'brand', direction: 'ASC'} );

If you need to sort the result for two or more attributes you can't use the datastore or EntityManager and would have to write this using the datastore's specific implementation.

Paging

Some of the finder methods accept a paging parameter which influences the result size.

Paging propertyTypeDescription
sizenumberthe size of the result set
pagenumberthe page of the result set starting with 0

To get a reliable result you should use the paging parameter always together with the sort parameter.

This example would give you the 3 cars with the highest power.

const Car = runtime.entityManager('Car'); 
const cars = await Car.findAll( {field: 'power', direction: 'DESC'}, { page: 0, size: 3 } );

Entity Item