Describes utilities in the Javascript API to access and manipulate application data.

sys.data

This package contains methods and classes to work with data in your application. You will find utilities to query data, create, update or delete records, as well as other more advanced operations like aggregation and execution of actions.

findById(entityName, id)

Finds a record by its ID. If the record is not found, null will be returned.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

id

string

yes

ID of the record to find

Returns

sys.data.Record - Record or null if not found.

Exceptions

badRequest

If entityName is not valid or ID is not a valid record ID.

Samples

// finds one company by its ID

var company = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
if (company) {
  log(company.label());
} else {
  log('company not found');
}

find(entityName, queryMap)

Finds records on the given entity according to a query map object. You get a result set you can iterate to fetch records.

It is important to notice that while you iterate it is possible that records are returned more than once. This could happen if records are updated in the middle (inside the iteration or by another thread), so you should be prepared for this if it happens.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

queryMap

object

no

The query map object used to filter records. Check the Query language documentation for the query map version.

Returns

sys.commons.ResultSet - A result set that returns sys.data.Record objects when iterated.

Exceptions

badRequest

If entityName or queryMap are invalid.

Samples

// iterates over all companies

var companies = sys.data.find('companies', {});
while (companies.hasNext()) {
  log(companies.next().label());
}

// finds using a query

var companies = sys.data.find('companies', {type: 'a', _sortField: 'name', _sortType: 'asc'});
while (companies.hasNext()) {
  log(companies.next().label());
}

find(queryBuilder)

Finds records on the given entity according to a query builder object. You get a result set you can iterate to fetch records.

It is important to notice that while you iterate it is possible that records are returned more than once. This could happen if records are updated in the middle (inside the iteration or by another thread), so you should be prepared for this if it happens.

Parameters

Name Type Required Default Description

queryBuilder

sys.data.Query

yes

The query builder object used to filter records. Check the Query language documentation for the query builder version.

Returns

sys.commons.ResultSet - A result set that returns sys.data.Record objects when iterated.

Exceptions

badRequest

If queryBuilder is invalid.

Samples

// iterates over all companies

var query = sys.data.createQuery('companies');
var companies = sys.data.find(query);
while (companies.hasNext()) {
  log(companies.next().label());
}

// finds using a query

var query = sys.data.createQuery('companies')
    .field('type').equals('a')
    .sortBy('name', 'asc');
var companies = sys.data.find(query);
while (companies.hasNext()) {
  log(companies.next().label());
}

findOne(entityName, queryMap)

Finds one record based on a query map object. If there query returns more than one result, the first one will be returned.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

queryMap

object

no

The query map object used to filter records. Check the Query language documentation for the query map version.

Returns

sys.data.Record - The first record found or null if there are no matching records for the given query.

Exceptions

badRequest

If entityName or queryMap are invalid.

Samples

// finds one copmany where type is 'b'

var company = sys.data.findOne('companies', {type: 'b'});
log(company.label());

findOne(queryBuilder)

Finds one record based on a query builder object. If there query returns more than one result, the first one will be returned.

Parameters

Name Type Required Default Description

queryBuilder

sys.data.Query

no

The query builder object used to filter records. Check the Query language documentation for the query builder version.

Returns

sys.data.Record - The first record found or null if there are no matching records for the given query.

Exceptions

badRequest

If queryBuilder is invalid.

Samples

// finds one copmany where type is 'b'

var query = sys.data.createQuery('companies')
    .field('type').equals('b');
var company = sys.data.findOne(query);
log(company.label());

count(entityName, queryMap)

Counts records matching the criteria in the query map object. Keep in mind that some options in the query language like size and offset will be ignored.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

queryMap

object

no

The query map object used to filter records. Check the Query language documentation for the query map version.

Returns

number - The number of records matching the criteria.

Exceptions

badRequest

If entityName or queryMap are invalid.

Samples

// counts companies where type is 'a'

var count = sys.data.count('companies', {type: 'a'});
log('count: '+count);

count(queryBuilder)

Counts records matching the criteria in the query builder object. Keep in mind that some options in the query language like size and offset will be ignored.

Parameters

Name Type Required Default Description

queryBuilder

sys.data.Query

no

The query builder object used to filter records. Check the Query language documentation for the query builder version.

Returns

number - The number of records matching the criteria.

Exceptions

badRequest

If queryBuilder is invalid.

Samples

// counts companies where type is 'a'

var query = sys.data.createQuery('companies')
    .field('type').equals('b');
var count = sys.data.count(query);
log('count: '+count);

aggregate(entityName, aggregateQueryMap)

Allows to perform aggregation operations like sum, average and count over an entity. This version uses an aggregate query map. Check the documentation for Aggregate queries.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

aggregateQueryMap

object

yes

This is the aggregate query map object that defines the operations to perform. Check the documentation for Aggregate queries.

Returns

sys.commons.ResultSet - A result set that returns JSON objects when iterated. The structure of this object depends on the aggregation operations performed. Check the documentation for Aggregate queries.

Exceptions

badRequest

If entityName or aggregateQueryMap are invalid.

Samples

// sums up the total number of skills per customer

var resultSet = sys.data.aggregate('contacts', [
  {match: {'company.isCustomer': true}},
  {group: {by: 'company', totalSkills: 'sum(numberOfSkills)'}}
]);
while (resultSet.hasNext()) {
  var result = resultSet.next();
  // the format of the result is a simple object you can stringify
  log(JSON.stringify(result));
}

// finds contacts with more skills on each company

var resultSet = sys.data.aggregate('contacts', [
  {sort: {'numberOfSkills': 'desc'}},
  {group: {
      by: 'company',
      firstName: 'first(firstName)',
      lastName: 'first(lastName)',
      skills: 'first(numberOfSkills)'
    }
  }
]);
while (resultSet.hasNext()) {
  var result = resultSet.next();
  // the format of the result is a simple object you can stringify
  log(JSON.stringify(result));
}

aggregate(aggregateQueryBuilder)

Allows to perform aggregation operations like sum, average and count over an entity. This version uses an aggregate query builder. Check the documentation for Aggregate queries.

Parameters

Name Type Required Default Description

aggregateQueryBuilder

object

yes

This is the aggregate query builder that defines the operations to perform. Check the documentation for Aggregate queries.

Returns

sys.commons.ResultSet - A result set that returns JSON objects when iterated. The structure of this object depends on the aggregation operations performed. Check the documentation for Aggregate queries.

Exceptions

badRequest

If aggregateQueryBuilder are invalid.

Samples

// sums up the total number of skills per customer

var query = sys.data.createAggregateQuery('contacts');
query.match().field('company.isCustomer').equals(true);
query.group().accumulate('totalNumberOfSkills').sum('numberOfSkills');
var resultSet = sys.data.aggregate(query);
while (resultSet.hasNext()) {
  log(JSON.stringify(resultSet.next()));
}

// finds contacts with more skills on each company

var query = sys.data.createAggregateQuery('contacts');
query.sort().by('numberOfSkills', 'desc');
query.group()
    .by('company')
    .accumulate('firstName').first('firstName')
    .accumulate('lastName').first('lastName')
    .accumulate('skills').first('numberOfSkills');
var resultSet = sys.data.aggregate(query);
while (resultSet.hasNext()) {
  log(JSON.stringify(resultSet.next()));
}

refresh(record)

Finds the latest version of the record in order to make sure it is up-to-date. This is useful so you know you have the latest version of the record and you won’t get an optimistic locking exception when saving it.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record to refresh.

Returns

sys.data.Record - The latest version of the record. It could return null if the record doesn’t exist anymore.

Exceptions

badRequest

If record is not valid.

Samples

// refreshes a company record

var company = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
// ...
// some long operation happens in the middle
// ...
company = sys.data.refresh(company);
if (company) {
  log(company.label());
} else {
  log('company was deleted');
}

save(record, options)

Saves a record in the database, making changes permanent. If the record was already saved (it has an ID that exists in the entity), it will be updated.

This method will perform all validation rules defined in the entity and its fields. Additionally it will check the version of the record to make sure no changes are overridden. If version doesn’t match, an optimistic locking exception will be thrown.

Once the record is saved successfully the following events will be triggered:

  • On record create: if the record is new and was created, this event is triggered. Check the parameter options to change this behavior.
  • On record change: if the record already existed in the database, this event is triggered. Check the parameter options to change this behavior.
  • Cascade updates: if the modification or creation of the record impacts other records, a background job will be created to updates them. Check the parameter options to change this behavior.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record to save into the database. Keep in mind that this object will be updated with the saved version of the record. For example, an ID will be set if not present and calculated fields will be there.

options

object

no

This is a map with options that can change the behavior of the save and some of them could help to improve import performance when there are a lot of records. These are the options:

  • calculateFields: if false when record is saved calculated fields won’t be evaluated and will be left in null. Default is true.
  • performValidations: indicates if validations should be performed over the record to save. Keep in mind that type validations are always performed. This flag works with validations defined in type rules. Default is true.
  • filterByReadWriteAccess: setting this flag to false makes the save process to ignore the read/write access options defined for the field, so all fields will be saved into the database. Default is true.
  • triggerEvents: if false events like on record create or change won’t be triggered. Default is true.
  • defaultValues: if false default values during save won’t be set. Default is true.
  • cascadeOperations: if false cascade update to update relationship fields or aggregate fields won’t be executed. Default is true.

Returns

sys.data.Record - The saved or updated record. The ID will be set and calculated or default values will be there.

Exceptions

validationErrors

If record doesn’t meet validation rules defined for the entity.

optimisticLocking

If record is an old version

badRequest

If record is not valid.

notFound

If record is being updated (it has an ID) and it is not found in the database.

Samples

// updates a field in a company

var company = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
company.field('notes').val('modified notes');
// you don't need to reassign the 'company' variable because the parameter will be updated
sys.data.save(company);
// ...
// do some other changes and save again
company.field('notes').val('another modification');
sys.data.save(company);

// catches validation errors

var company = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
company.field('type').val('invalid');
try {
  sys.data.save(company);
} catch (e) {
  log(e.code()+': '+e.message());
}

// optimistic locking exception

var company1 = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
var company2 = sys.data.findById('companies', '57fd2d65e4b0ce322b0c8665');
company1.field('notes').val('modified notes');
sys.data.save(company1);
try {
  // this will throw an optimistic locking exception because the record was modified in the middle
  sys.data.save(company2);
} catch (e) {
  log(e.code()+': '+e.message());
}

createRecord(entityName)

Creates a new empty sys.data.Record object. This record is not saved into the database until you call save().

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

Returns

sys.data.Record - The empty record object.

Exceptions

badRequest

If entityName is not valid.

Samples

// creates a new company

var company = sys.data.createRecord('companies');
company.field('name').val('test company '+parseInt(Math.random()*999));
// saves the new company into the database
sys.data.save(company);
company = sys.data.findById('companies', company.id());
log('saved company: '+company.label());
// clean up the created company
sys.data.remove(company);

remove(record)

Deletes a record from the database.

When the record is deleted successfully the following events are triggered:

  • On record delete
  • Cascade updates: if the deletion of the record has impact on other records, a background job will be created to update them.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record to remove from the database.

Returns

sys.data.Record - The record that was removed.

Exceptions

badRequest

If record is not valid.

notFound

If record is not found in the database.

Samples

// creates and deletes a company

var company = sys.data.createRecord('companies');
company.field('name').val('test company '+parseInt(Math.random()*999));
// saves the new company into the database
sys.data.save(company);
// deletes the just created company
var deletedCompany = sys.data.remove(company);
log('company ['+deletedCompany.label()+'] was deleted');

delete(entityName, queryMap, options)

Deletes records matching the criteria in the query map object. Keep in mind that some options in the query language like size and offset will be ignored.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

queryMap

object

no

The query map object used to filter records. Check the Query language documentation for the query map version.

options

object

no

This is a map with options that can change the behavior of the deletion and some of them could help to improve delete performance when there are a lot of records. These are the options:

  • triggerEvents: if false events of deletion won’t be triggered. Default is true.
  • cascadeOperations: if false cascade update to update relationship fields or aggregate fields won’t be executed. Default is true.
  • lowPriority: set job as low priority will make the deletion only happen when there are no many jobs running. Default is false.

Returns

string - Identifier of deletion job.

Exceptions

badRequest

If entityName or queryMap are invalid.

Samples

// deletes active companies

var jobId = sys.data.delete('companies', {active: true});
log('jobId: '+jobId);
sys.jobs.waitForJob(jobId, 'FINISHED', 1000*10);

delete(queryBuilder, options)

Deletes records matching the criteria in the query builder object. Keep in mind that some options in the query language like size and offset will be ignored.

Parameters

Name Type Required Default Description

queryBuilder

sys.data.Query

no

The query builder object used to filter records. Check the Query language documentation for the query builder version.

options

object

no

This is a map with options that can change the behavior of the deletion and some of them could help to improve delete performance when there are a lot of records. These are the options:

  • triggerEvents: if false events of deletion won’t be triggered. Default is true.
  • cascadeOperations: if false cascade update to update relationship fields or aggregate fields won’t be executed. Default is true.
  • lowPriority: set job as low priority will make the deletion only happen when there are no many jobs running. Default is false.

Returns

string - Identifier of deletion job.

Exceptions

badRequest

If queryBuilder is invalid.

Samples

// deletes companies where type is 'b'

var query = sys.data.createQuery('companies')
    .field('type').equals('b');
var jobId = sys.data.delete(query);
log('jobId: '+jobId);
sys.jobs.waitForJob(jobId, 'FINISHED', 1000*10);

importRecords(entityName, fileId, options)

Allows to import records from a CSV file that has to be already uploaded. The file could be in a field inside a record, it could be coming from an endpoint like FTP or HTTP, or you can create it in the script.

Rules for importing from a CSV file are the same as when you import a CSV from the app runtime UI. So check the documentation of imports to understand how they work.

Finally keep in mind that for each record you import the same events as with the save() method will be triggered.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

fileId

string

yes

The ID of the file to import. This is a private file uploaded into the app previously. For example if could have been uploaded through the app runtime UI into a file field, it could have been uploaded from an HTTP or FTP endpoint, or you can create the file using a script. Check the samples to see the different options.

options

object

no

This is a map with options that can change the behavior of the import and some of them could help to improve import performance when there are a lot of records. These are the options:

  • skipRecordsWithInvalidFields: when true, if some of the fields cannot be converted or aren’t valid, ç they will be set to null and we try to save the record anyways. If this is false an exception will be thrown and we won’t attempt to import the record. Default is true.
  • calculateFields: if false when records are imported calculated fields won’t be evaluated and will be left in null. Default is true.
  • performValidations: indicates if validations should be performed. Keep in mind that type validations are always performed. This flag works with validations defined in type rules. Default is true.
  • filterByReadWriteAccess: setting this flag to false makes the import process to ignore the read/write access options defined for the field, so all fields will be imported into the database. Default is true.
  • triggerEvents: if false events like on record create or change won’t be triggered. Default is true.
  • defaultValues: if false default values in imported records won’t be set. Default is true.
  • cascadeOperations: if false cascade update to update relationship fields or aggregate fields won’t be executed. Default is true.
  • lowPriority: set job as low priority will make the import only happen when there are no many jobs running. Default is false.

Returns

string - The ID of the background job in charge of the import. To check the progress of the import (as well as errors) you should check the status of the background job.

Exceptions

badRequest

If entityName or fileId is not valid.

Samples

// creates a CSV file, imports it into 'companies' entity using low priority and then does a clean up to remove those records

var total = 10;
var fileWriter = sys.files.create('companies.csv', 'text/csv');
try {
  fileWriter.writeHeaders(['name', 'state', 'type']);
  for (var i = 0; i < total; i++) {
    log('writting row '+i);
    fileWriter.writeRow(['test'+i, 'active', 'a']);
  }
} finally {
  fileWriter.close();
}

// import data
var jobId = sys.data.importRecords('companies', fileWriter.descriptor().id(), {lowPriority: true});
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log(total+' records imported!');

// clean up
var testRecords = sys.data.find('companies', {name: 'like(test)'});
var recordsRemoved = 0;
while (testRecords.hasNext()) {
  sys.data.remove(testRecords.next());
  recordsRemoved++;
}
log(recordsRemoved+' records removed!');

// imports records from a file field

// find record with file
var fileRecord = sys.data.findOne('files', {code: 'test-companies'});

// import data
var jobId = sys.data.importRecords('companies', fileRecord.field('file').id(), {lowPriority: true});
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log('records imported!');

// clean up
var testRecords = sys.data.find('companies', {name: 'like(test)'});
var recordsRemoved = 0;
while (testRecords.hasNext()) {
  sys.data.remove(testRecords.next());
  recordsRemoved++;
}
log(recordsRemoved+' records removed!');

executeAction(entityName, queryMap, actionName, params)

Executes an action in the background over the records returned by the query.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

queryMap

object

yes

The query map object used to filter records. Check the Query language documentation for the query map version.

actionName

string

yes

The name of the action to execute.

params

object

no

If the action has parameters you should put them here. The format is the same used by the REST API.

Returns

string - The ID of the background job in charge of executing the action over all records. To check progress (as well as errors) you should check the status of the background job.

Exceptions

badRequest

If entityName, queryMap or actionNAme are not valid.

Samples

// executes the action 'logSomething' over 10 company records of type 'a'

var jobId = sys.data.executeAction('companies', {type: 'a', _size: 10}, 'logSomething');
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log('completed!');

// executes the action 'logSomething' over 10 company records of type 'a', sending a parameter

var jobId = sys.data.executeAction('companies', {type: 'a', _size: 10}, 'logSomething', {param1: 'a', param2: 'b'});
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log('completed!');

executeAction(queryBuilder, actionName, body)

Executes an action in the background over the records returned by the query. This version uses a query builder.

Parameters

Name Type Required Default Description

queryBuilder

sys.data.Query

yes

The query builder object used to filter records. Check the Query language documentation for the query builder version.

actionName

string

yes

The name of the action to execute.

body

object

no

If the action has parameters you should put them here. The format is the same used by the REST API.

Returns

string - The ID of the background job in charge of executing the action over all records. To check progress (as well as errors) you should check the status of the background job.

Exceptions

badRequest

If queryBuilder or actionNAme are not valid.

Samples

// executes the action 'logSomething' over 10 company records of type 'a'

var query = sys.data.createQuery('companies')
    .field('type').equals('a')
    .size(10);
var jobId = sys.data.executeAction(query, 'logSomething');
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log('completed!');

// executes the action 'logSomething' over 10 company records of type 'a', sending a parameter

var query = sys.data.createQuery('companies')
    .field('type').equals('a')
    .size(10);
var jobId = sys.data.executeAction(query, 'logSomething', {param1: 'a', param2: 'b'});
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);
log('completed!');

executeGlobalAction(entityName, actionName, params)

Performs the execution of a global action.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

actionName

string

yes

The name of the action to execute.

params

object

no

If the action has parameters you should put them here. The format is the same used by the REST API.

Returns

string - The ID of the background job in charge of executing the global action. To check progress (as well as errors) you should check the status of the background job.

Exceptions

badRequest

If entityName or actionName are not valid.

Samples

// executes the global action 'quickAdd' on companies entity and then finds the created company and log some properties

var actionParams = {'name': 'Quick company', 'address': {'addressLine1': 'Siempre viva street'}};
var jobId = sys.data.executeGlobalAction('companies', 'quickAdd', actionParams);
sys.jobs.waitForJob(jobId, 'FINISHED', 1000*10);
var dataCursor = sys.data.find('companies', {name: 'Quick company'});
var dataFound = dataCursor.next();
log(dataFound.id());
log(dataFound.label());
log(dataFound.field('address.addressLine1').val());

tryLock(record, timeout)

Tries to acquire a lock for a specified record. This method should be used when multiple threads try to access the same record. This is important when you have listeners or actions that could be executed concurrently.

If the lock has been already acquiered, this method will wait until it is released. If the lock cannot be acquiered within the specified timeout it will return null instead of the record.

Keep in mind that if you lock the record again within the same context of execution, the lock will be granted immediately. This means it follows the re-entrant lock concept.

You should always release the lock using unlock() and you should do that in a finally block to make sure that happens. However, in case you forget to do it, the platform will free the locks at the end of the script execution if that was not done before.

Important! The lock will be kept for a maximum of 30 minutes, then it will be automatically released.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record object.

timeout

number

yes

The maximum time in seconds to wait for the lock be acquired. If the lock cannot be acquired it returns a null.

Returns

sys.data.Record - The updated version of the record when the lock was acquired, otherwise a null object.

Exceptions

badRequest

If record or timeout are not valid.

notFound

If record is not found in the database.

Samples

// locks a record for 20 seconds

var company = sys.data.findOne('companies', {name:'Blogpad'});
company = sys.data.tryLock(company);
try {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
} finally {
  sys.data.unlock(company);
}

lock(record, timeout)

Acquires a lock for a specified record. This method should be used when multiple threads try to access the same record. This is important when you have listeners or actions that could be executed concurrently.

If the lock has been already acquiered, this method will wait until it is released. If the lock cannot be acquiered within the specified timeout an exception will be thrown.

Keep in mind that if you lock the record again within the same context of execution, the lock will be granted immediately. This means it follows the re-entrant lock concept.

You should always release the lock using unlock() and you should do that in a finally block to make sure that happens. However, in case you forget to do it, the platform will free the locks at the end of the script execution if that was not done before.

Important! The lock will be kept for a maximum of 30 minutes, then it will be automatically released.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record object.

timeout

number

no

300000 (5 minutes)

The maximum time in milliseconds to wait for the lock be acquired. If the lock cannot be acquired and exception will be thrown.

Returns

sys.data.Record - The updated version of the record when the lock was acquired.

Exceptions

badRequest

If record or timeout are not valid.

notFound

If record is not found in the database.

timeout

If the lock couldn’t be acquiered within the specified timeout.

Samples

// locks a record for 20 seconds

var company = sys.data.findOne('companies', {name:'Blogpad'});
try {
  company = sys.data.lock(company);
  try {
    // write some code here to update the company
    // if from the app you try to update the record it will be blocked
    // until the lock is released
    log('do something');
    sys.utils.script.wait(20000);
  } finally {
    sys.data.unlock(company);
  }
} catch (le) {
  sys.logs.error('Error acquiring lock');
}

// locks a record several times

var company = sys.data.findOne('companies', {name:'Blogpad'});
company = sys.data.lock(company);
// you can lock again in the same context as it is a reentrant lock
company = sys.data.lock(company);
// you need to unlock twice to release it
sys.data.unlock(company);
sys.data.unlock(company);

tryLockById(entityName, recordId, timeout)

Tries to acquire a lock for a specified record using its ID (useful when you don’t have the record object but just the ID). This method should be used when multiple threads try to access the same record. This is important when you have listeners or actions that could be executed concurrently.

If the lock has been already acquiered, this method will wait until it is released. If the lock cannot be acquiered within the specified timeout it returns a null.

Keep in mind that if you lock the record again within the same context of execution, the lock will be granted immediately. This means it follows the re-entrant lock concept.

You should always release the lock using unlock() and you should do that in a finally block to make sure that happens. However, in case you forget to do it, the platform will free the locks at the end of the script execution if that was not done before.

Important! The lock will be kept for a maximum of 30 minutes, then it will be automatically released.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

recordId

string

yes

The ID of the record to acquire the lock.

timeout

number

yes

The maximum time in milliseconds to wait for the lock be acquired. If the lock cannot be acquired it returns a null.

Returns

sys.data.Record - The updated version of the record when the lock was acquired.

Exceptions

badRequest

If recordId or timeout are not valid.

notFound

If record with ID recordId is not found in the database.

Samples

// locks a record for 20 seconds

var company = sys.data.lockById('companies', '57fd2d65e4b0ce322b0c8565');
try {
  if (company) {
    log('company ['+company.label()+'] is locked');
    // write some code here to update the company
    // if from the app you try to update the record it will be blocked
    // until the lock is released
    log('do something');
    sys.utils.script.wait(20000);
  }
} finally {
  log('unlocking company ['+company.label()+']');
  sys.data.unlock(company);
}

lockById(entityName, recordId, timeout)

Acquires a lock for a specified record using its ID (useful when you don’t have the record object but just the ID). This method should be used when multiple threads try to access the same record. This is important when you have listeners or actions that could be executed concurrently.

If the lock has been already acquiered, this method will wait until it is released. If the lock cannot be acquiered within the specified timeout an exception will be thrown.

Keep in mind that if you lock the record again within the same context of execution, the lock will be granted immediately. This means it follows the re-entrant lock concept.

You should always release the lock using unlock() and you should do that in a finally block to make sure that happens. However, in case you forget to do it, the platform will free the locks at the end of the script execution if that was not done before.

Important! The lock will be kept for a maximum of 30 minutes, then it will be automatically released.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

recordId

string

yes

The ID of the record to acquire the lock.

timeout

number

no

300000 (5 minutes)

The maximum time in milliseconds to wait for the lock be acquired. If the lock cannot be acquired and exception will be thrown.

Returns

sys.data.Record - The updated version of the record when the lock was acquired.

Exceptions

badRequest

If recordId or timeout are not valid.

notFound

If record with ID recordId is not found in the database.

timeout

If the lock couldn’t be acquiered within the specified timeout.

Samples

// locks a record for 20 seconds

try {
  var company = sys.data.lockById('companies', '57fd2d65e4b0ce322b0c8565');
  log('company ['+company.label()+'] is locked');
  try {
    // write some code here to update the company
    // if from the app you try to update the record it will be blocked
    // until the lock is released
    log('do something');
    sys.utils.script.wait(20000);
  } finally {
    log('unlocking company ['+company.label()+']');
    sys.data.unlock(company);
  }
} catch(le) {
  sys.logs.error('Log could not have been acquired', le);
}

unlock(record)

Releases a lock that was previously acquired.

If the lock was acquired several times, it needs to be released several times as well.

Parameters

Name Type Required Default Description

record

sys.data.Record

yes

The record object.

Exceptions

badRequest

If record is not valid.

notFound

If record is not found in the database.

Samples

// locks a record for 20 seconds und unlocks it at the end

var company = sys.data.findOne('companies', {name:'Blogpad'});
company = sys.data.lock(company);
try {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
} finally {
  sys.data.unlock(company);
}

unlockById(entityName, recordId)

Releases a lock that was previously acquired.

If the lock was acquired several times, it needs to be released several times as well.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

recordId

string

yes

The ID of the record to unlock.

Exceptions

badRequest

If recordId is not valid.

notFound

If record with ID recordId is not found in the database.

Samples

// locks a record for 20 seconds und unlocks it at the end

var company = sys.data.lockById('companies', '57fd2d65e4b0ce322b0c8565');
log('company ['+company.label()+'] is locked');
try {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
} finally {
  log('unlocking company ['+company.label()+']');
  sys.data.unlockById('companies', '57fd2d65e4b0ce322b0c8565');
}

replaceRefs(from, to)

Replaces all references pointing to from with to. For example, you have a two companies and under each company you have contacts and orders. You want to merge those two companies so all relationship fields pointing to company1 should be changed to company2:

sys.data.replaceRefs(company1, company2);

Important! This change will be applied to all records in all entities and there is not way to roll it back.

Parameters

Name Type Required Default Description

from

sys.data.Record

yes

The record you want to replace its references.

to

sys.data.Record

no

The record you want to reference instead of from. This can be null and reference will be removed.

Returns

string - The ID of the background job in charge of replacing references over all records. To check progress (as well as errors) you should check the status of the background job.

Exceptions

badRequest

If from or to are not valid.

notFound

If toId is provided but not record is found with that ID in the database.

Samples

// locks a record for 20 seconds und unlocks it at the end

// create 2 companies
var company1 = sys.data.createRecord('companies');
company1.field('name').val('testA');
sys.data.save(company1);
var company2 = sys.data.createRecord('companies');
company2.field('name').val('testB');
sys.data.save(company2);

// create 2 contacts associated to company1
var contact1 = sys.data.createRecord('contacts');
contact1.field('company').val(company1);
contact1.field('firstName').val('contact1');
contact1.field('lastName').val('test');
contact1.field('email').val('contact1@test.com');
sys.data.save(contact1);
var contact2 = sys.data.createRecord('contacts');
contact2.field('company').val(company1);
contact2.field('firstName').val('contact2');
contact2.field('lastName').val('test');
contact2.field('email').val('contact2@test.com');
sys.data.save(contact2);

// replace references from company1 to company2
var jobId = sys.data.replaceRefs(company1, company2);
sys.jobs.waitForJob(jobId, 'FINISHED', 60*1000);

// check if references were modified
contact1 = sys.data.refresh(contact1);
contact2 = sys.data.refresh(contact2);
log(contact1.field('company').label());
log(contact2.field('company').label());

createQuery(entityName)

Initializes and returns a sys.data.Query object. Please check out the documentation for the Query language.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

Returns

sys.data.Query - The query builder object for the given entity.

Exceptions

badRequest

If entityName is not valid.

Samples

// creates a query to find companies with type 'a'

var query = sys.data.createQuery('companies');
query.field('type').equals('a');
log('total A companies: '+sys.data.count(query));

createAggregateQuery(entityName)

Initializes and returns a sys.data.AggregateQuery object. Please check out the documentation for Aggregate queries.

Parameters

Name Type Required Default Description

entityName

string

yes

The name of the entity

Returns

sys.data.AggregateQuery - The aggregate query builder object for the given entity.

Exceptions

badRequest

If entityName is not valid.

Samples

// creates an aggregate query to find the contact with more skills per company

var query = sys.data.createAggregateQuery('contacts');
query.sort().by('numberOfSkills', 'desc');
query.group()
    .by('company')
    .accumulate('firstName').first('firstName')
    .accumulate('lastName').first('lastName')
    .accumulate('skills').first('numberOfSkills');
var resultSet = sys.data.aggregate(query);
while (resultSet.hasNext()) {
  log(JSON.stringify(resultSet.next()));
}

sys.data.Record

Represents a record of an entity. It contains methods to read and write fields, execute actions and do some other operations.

All operations that read data will return this object. For example sys.data.findOne() or sys.data.findById() return objects of sys.data.Record.

Record objects can be created using the method sys.data.createRecord():

var company = sys.data.createRecord('companies');
company.field('name').val('test company');
sys.data.save(company);

id()

Returns the ID of the record. If this is a new record that hasn’t been saved into the database, this will return null.

Returns

string - The ID of the record.

Samples

// finds 10 companies and logs their ID

var companies = sys.data.find('companies', {type: 'a', _size: 10});
while (companies) {
  var company = companies.next();
  log('ID: '+company.id());
}

label()

Returns the label of the record based on the instance label expression defined in the entity. Keep in mind that the label is calculated when the record is saved into the database. New records that haven’t saved won’t have a label. Also, records that were modified but not updated might have an outdated label.

Returns

string - The label of the record.

Samples

// finds 10 companies and logs their label

var companies = sys.data.find('companies', {type: 'a', _size: 10});
while (companies.hasNext()) {
  var company = companies.next();
  log('Label: '+company.label());
}

entityName()

Returns the name of the entity the record belongs to.

Returns

string - The name of the entity

Samples

// prints the name of the entity

var company = sys.data.findOne('companies', {type: 'a'});
log('Entity name: '+company.entityName());

entitId()

Returns the ID of the entity the record belongs to.

Returns

string - The ID of the entity

Samples

// prints the ID of the entity

var company = sys.data.findOne('companies', {type: 'a'});
log('Entity ID: '+company.entityId());

field(path)

Returns the wrapper of the field at the given path. Wrappers have different methods that allow to access data in different ways and they are type-specific. This means each data type will provide different methods. Please check the documentation of sys.data.Wrapper for more information.

What’s important to remember is that this method doesn’t return the actual value, but an object of type sys.data.Wrapper (depending on the type the wrapper could offer more utilities) you can use to read and manipulate the value. For example:

// 'company' is a record in entity 'companies'

// get the name of the company
var name = company.field('name').val();

// set the name of the company
record.field('name').val('new name');

It is possible to access nested fields:

// 'contact' is a record in entity 'contacts'

// get the state of contacts
var state = company.field('address.state').val();

// set the state of the contact
record.field('address.state').val('NY');

If fields are multi-valued you can access them using an index:

// 'company' is a record in entity 'companies'

// get the first state for a company
var state = company.field('addresses[0].state').val();
// the above line is the same as this one:
var state = company.field('addresses').first().field('state').val();

// set a value in a multi-valued field
company.field('addresses[1].state').val('CA');

If the index is out of bounds, no exception will be thrown. Instead you will get null if you are trying to read the value or, if you are trying to set the value, a new element will be created.

If you try to access a multi-valued field, you will get a sys.data.ManyWrapper object. This object provides several methods to access the items inside:

// 'company' is a record in entity 'companies'

// gets the state of the first address
company.field('addresses').first().field('state').val();

// gets the state of the last address
company.field('addresses').last().field('state').val();

// iterates over all addresses
company.field('addresses').each(function(address) {
  log('State: '+address.field('state').val());
});

Please check the documentation of sys.data.ManyWrapper for more information.

Finally, if the path is not a valid field, an exception will be thrown.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field. It could be a nested or multi-valued field.

Returns

sys.data.Wrapper or sys.data.ManyWrapper - A wrapper that you can use to read and manipulate the value.

Exceptions

badRequest

If path is invalid.

Samples

// prints the name of 10 companies

var companies = sys.data.find('companies', {_size: 10});
while (companies.next()) {
  var company = companies.next();
  log('name: '+company.field('name').val());
}

// creates a new company and sets the name

var company = sys.data.createRecord('companies');
company.field('name').val('test company');
sys.data.save(company);

parent()

This is useful when you are working on records that have a prefix set. For example let’s suppose you have an entity with the following structure:

  • name
  • orderLines (multi-valued)
    • product
    • quantity
    • notes (multi-valued)
      • note
      • date
      • user
      • calculatedField

Field calculatedField can have a script to calculate its value and you will find the variable parentField in there. This varible is a record object, but it has a prefix for that particular notes field (like orderLines[2].notes[1]). This is important because you might need to know the path of your field, so you can write expressions like this one:

return parentField.parent().parent().field('name').val() + ' ' +
  parentField.parent().field('product').name() + ' ' +
  parentField.field('note').val();

Returns

sys.data.Record - The record object with a prefix set to the parent field

Samples

// this is the value expression for a calculated field taken the sample in the description

return parentField.parent().parent().field('name').val() + ' ' +
  parentField.parent().field('product').name() + ' ' +
  parentField.field('note').val();

copy()

This method allows to get a copy of a record and save it as a new one. This is helpful when creating several similar records just changes a few fields

Returns

sys.data.Record - The record object without identifiers

Samples

// this is the copy of record with name changed and saved.

var copy = record.copy();
copy.field('name').val('newOne');
sys.data.save(copy);

isNew()

If the record has an ID set, this method will return false. Otherwise it will return true.

Returns

boolean - true if the record doesn’t have an ID, false otherwise.

Samples

// check if record is new before and after saving

var company = sys.data.createRecord('companies');
company.field('name').val('test1');
log('new: '+company.isNew());
sys.data.save(company);
log('new: '+company.isNew());

action(actionName, params)

Executes the given action over the record. The record has to be saved into the database.

If the action has parameters you can send them in the second argument.

The response will be different based on the configuration. There are two possible responses:

  • Record: if the doesn’t return any custom response, then the updated record is returned by this method.
  • Custom action’s response: if the the action returns a custom response, then that response is returned.

Parameters

Name Type Required Default Description

actionName

string

yes

The name of the action to execute.

params

object

no

If the action has parameters you should put them here. The format is the same used by the REST API.

Returns

object - An object of type sys.data.Record or a custom response if the action has been configured to do that.

Samples

// executes the action 'logSomething' over a company

var company = sys.data.findOne('companies', {name: 'Blogpad'});
company.action('logSomething');
log('completed!');

// executes the action 'logSomething' over a company with parameters

var company = sys.data.findOne('companies', {name: 'Blogpad'});
company.action('logSomething', {param1: 'a', param2: 'b'});
log('completed!');

history()

Returns an object of type sys.data.RecordHistoryLogs to query history logs.

See sys.data.RecordHistoryLogs for more information on how to query record’s history logs.

Returns

sys.data.RecordHistoryLogs - An object of type sys.data.RecordHistoryLogs to query history logs

Samples

// prints who created the record

var company = sys.data.findOne('companies', {name: 'Blogpad'});
log('creator: '+company.history().createLog().user());

toJson(options)

Converts the record to its native JSON representation.

Parameters

Name Type Required Default Description

options

object

no

These options allow to control how the record will be converted. Available options are:

  • fields: By default all fields will be fetched. If you want to specify which fields you want to fetch, you can pass this parameter. You can specify many fields separating them by commas. System field will always be returned (id, version, etc.).
  • relationshipsToFetch: A comma-separated list of relationship fields that will be fetched within the record. For example if an entity has relationship fields named company and region, you could fetch those referenced records like this:

      relationshipsToFetch: 'company,region'
    
  • format: The format to use to fetch the fields. There are two options: native and plainText. The first one shows the raw value of each field. The second one, plainText, returns the values of the fields converted using the display option of each field. The default value is native.
  • user: if the format is plainText we would need the user to convert values with the correct internationalization and timezones. Default is current user.

Returns

object - A key-value JSON structure with the fields of the record converted to their native representation.

Samples

// converts a contact to the JSON representation

var record = sys.data.findOne('contacts', {email: 'gowensb1@google.ca'});
var recordJson = record.toJson({relatedFields: 'company'});
log('JSON version of record: ' + recordJson);

fromJson(recordJson)

Parses a JSON representation of the record.

Parameters

Name Type Required Default Description

recordJson

object

yes

A key-value object map containing the proper record representation. A partial record representation is allowed.

Samples

// copies contact info to a new person record using JSON representation

var contact = sys.data.findOne('contacts', {email: 'gowensb1@google.ca'});
var contactJson = record.toJson();
var person = sys.data.createRecord('people');
person.fromJson(contactJson);
log('Person after update: ' + person.toJson());

// performs a partial update of a contact

var person = sys.data.findOne('people', {sid: '20309721919'});
var contact = sys.data.findOne('contacts', {email: 'gowensb1@google.ca'});
contact.fromJson({
    phoneNumber: person.field('phoneNumber').val(),
    webSite: person.field('webSite').val()
});
log('Contact after update: ' + contact.toJson({}));

lock(callback)

Acquires a lock for current record. This method should be used when multiple threads try to access the same record. This is important when you have listeners or actions that could be executed concurrently.

If the lock has been already acquiered, this method will wait until it is released. If the lock cannot be acquiered within the specified timeout an exception will be thrown.

Keep in mind that if you lock the record again within the same context of execution, the lock will be granted immediately. This means it follows the re-entrant lock concept.

If you specify the callback parameter the lock will be released automatically. Additionally, once the callback is executed the record object will be refreshed automatically in case it was modified in the callback.

If you don’t specify the callback parameter you should always release the lock using unlock() and you should do that in a finally block to make sure that happens. However, in case you forget to do it, the platform will free the locks at the end of the script execution if that was not done before.

Parameters

Name Type Required Default Description

callback

function

no

This callback function is executed after the lock is acquired successfully. The acquired lock is released automatically after the execution of defined callback.

Samples

// locks a record for 20 seconds und unlocks it at the end

var company = sys.data.findOne('companies', {name:'Blogpad'});
company.lock();
try {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
} finally {
  company.unlock();
}

// locks a record for 20 seconds by specifying a callback

var company = sys.data.findOne('companies', {name:'Blogpad'});
company.lock(function (record) {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
  // at the end lock will be released automatically
});

unlock()

Releases a lock that was previously acquired.

If the lock was acquired several times, it needs to be released several times as well.

Samples

// locks a record for 20 seconds und unlocks it at the end

var company = sys.data.findOne('companies', {name:'Blogpad'});
company.lock();
try {
  // write some code here to update the company
  // if from the app you try to update the record it will be blocked
  // until the lock is released
  log('do something');
  sys.utils.script.wait(20000);
} finally {
  company.unlock();
}

sys.data.Wrapper

Every time you need to access or manipulate the value of a field using the Javascript API, you will do it through a wrapper. You will never create a wrapper manually. Instead object of type are created by method like sys.data.Record.field().

The wrapper provides some utilities to retrieve the value, change it, and depending on the type it could provide different services. Please check the documentation for each type here to see which utilities are available in the wrapper.

val()

Returns the value of the field. Keep in mind that this value can’t be different from the value in the REST API. For example a date time field is a number in the REST API respresenting the milliseconds after EPOCH. However this method will return a Date object. You should check each type’s documentation to see what’s the default format for it.

Keep in mind that if the field you are referencing is multivalue, it will return an array of values.

Returns

any or any[] - Returns the value of the field. If it is multi-valued it will return an array. Please check the type’s documentation to figure out what’s returned.

Samples

// get the value of different fields

var company = sys.data.findOne('companies', {name:'Voonyx'});

var nameWrapper = company.field('name');
log('name: '+nameWrapper.val());
// you could also use a shorter form
log('name: '+company.field('name').val());

// the wrapper for nested fields has utilities to access inner fields
var firstAddressWrapper = company.field('addresses[0]');
var stateWrapper = firstAddressWrapper.field('state');
log('state: '+stateWrapper.val());
// or you could use the shorter form
log('state: '+company.field('addresses[0]').field('state').val());
// or even shorter
log('state: '+company.field('addresses[0].state').val());

// some fields, like data time, use a different format from the REST API
// in this case the value is returned as a Date object
var lastUpdateWrapper = company.field('lastUpdate');
log('last update: '+lastUpdateWrapper.val());
log('last update millis: '+lastUpdateWrapper.val().getTime());
// date time also supports formatting the date
log('last update yyyy-MM-dd: '+company.field('lastUpdate').format('yyyy-MM-dd'));

// if the field is multi-valued, you will get an array of values
log('addresses: '+JSON.stringify(company.field('addresses').val()));

// if the field isn't multi-valued, but you the parent is an you don't specify
// an index, then the result will be an array as well
log('states: '+JSON.stringify(company.field('addresses.state').val()));

val(value)

Sets the value of the field. You should check the type’s documentation to see which formats are supported. For example a date time field will accept Date objects but also milliseconds from EPOCH in order to make things easier.

If the field is multi-valued you should provide an array with values. In this case you should also check the documentation for sys.data.ManyWrapper which contains some utilities to hanle multi-valued fields.

Parameters

Name Type Required Default Description

value

any

yes

The value to set in the field. Type depends on the field.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

Samples

// creates a record and changes some of the values

var company = sys.data.createRecord('companies');
// sets a text field
company.field('name').val('test 1');
// sets a date field using a Date object
company.field('startDate').val(new Date());
// you can also set a nested field directly
company.field('contactInformation.phoneNumber').val('111-222-3333');
company.field('contactInformation.email').val('test@test.com');
// you could also set nested fields with a map
company.field('contactInformation').val({
  phoneNumber: '444-555-6666',
  email: 'john@test.com'
});
// you can set a multi-valued field by sending an array
company.field('addresses').val([
  {
    addressLine: '63 test',
    zipCode: '12233'
  },
  {
    addressLine: '32 street',
    zipCode: '83672'
  }
]);
// you change a nested field inside a multi-valued field using an index
company.field('addresses[0].state').val('NY');

isEmpty()

If the field is empty, this method will return true. Usually a field is empty when its value is null. Some types might define additional rules, like text fields where an empty string is considered as an empty value.

If the field is multi-valued, it will be empty if it has no values.

Returns

boolean - Returns true if field is empty, false otherwise.

equals(value)

Checks if the value of the field is equal to the given value.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare with the value of the field. Type depends on the field.

Returns

boolean - Returns true if values are equal, false otherwise.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

sys.data.ManyWrapper

This class inherit from sys.data.Wrapper and it follows the same idea, but it works with multi-valued fields, with utilities to add values, check if one value is contained in the list, remove values, etc.

Same as with sys.data.Wrapper you won’t create it manually. Instead object of type are created by method like sys.data.Record.field().

add(value)

Adds an element at the end of the list.

Parameters

Name Type Required Default Description

value

any

yes

The element to add to the list. The type depends on the field.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

Samples

// adds a few elements to a list

var company = sys.data.createRecord('companies');
company.field('addresses').add({
  addressLine: '52 street',
  zipCode: '18231'
});
company.field('addresses').add({
  addressLine: '73 test',
  zipCode: '84873'
});

add(index, value)

Adds an element at the specified position in the list. Existing elements will be shifted to the right.

Parameters

Name Type Required Default Description

index

number

yes

The position in the list where the new element should be added.

value

any

yes

The element to add to the list. The type depends on the field.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

Samples

// adds an element at the first position of the list

var company = sys.data.createRecord('companies');
company.field('addresses').add({
  addressLine: '52 street',
  zipCode: '18231'
});
company.field('addresses').add({
  addressLine: '73 test',
  zipCode: '84873'
});
// this value will be inserted at the first position and other values will be shifted
company.field('addresses').add(0, {
  addressLine: '10 road',
  zipCode: '92743'
});

remove(value)

Removes the first occurrence of an element from the list. It doesn’t need to be the exact same object, but in order to compare the value the method sys.data.Wrapper.equals() will be used, which can be overridden by each type.

Parameters

Name Type Required Default Description

value

any

yes

The element to remove from the list. The type depends on the field.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

Samples

// removes an element from the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
log('skills: '+JSON.stringify(contact.field('skills').val()));
contact.field('skills').remove('Firewalls');
log('skills: '+JSON.stringify(contact.field('skills').val()));

remove(callback)

Removes elements where evaluation of the function returns true.

Parameters

Name Type Required Default Description

callback

function

yes

The function to evaluate if an element needs to be removed. It will receive the element wrapper as parameter and should return true if the element has to be removed or false otherwise.

Exceptions

badRequest

If callback is invalid.

Samples

// removes an element from the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+JSON.stringify(contact.field('skills').val()));
contact.field('skills').remove(function(element) {
  if (element.label() == 'WLAN' || element.label() == 'YouTube') {
    return true;
  } else {
    return false;
  }
});
log('skills: '+JSON.stringify(contact.field('skills').val()));

removeAt(index)

Removes an element from the list from the specified position.

Parameters

Name Type Required Default Description

index

number

yes

The position of the element to remove.

Exceptions

badRequest

If index is invalid.

Samples

// removes an element from the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+JSON.stringify(contact.field('skills').val()));
contact.field('skills').removeAt(1);
log('skills: '+JSON.stringify(contact.field('skills').val()));

removeAll()

Removes all elements from the list.

Samples

// removes all elements from the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+JSON.stringify(contact.field('skills').val()));
contact.field('skills').removeAll();
log('skills: '+JSON.stringify(contact.field('skills').val()));

each(callback)

Iterate over all elements in the list.

Parameters

Name Type Required Default Description

callback

function

yes

The function to that will process all elements. It will receive two parameters: the wrapper element and the current index of the iteration. In order to stop iteration it is possible to return false explicitly.

Exceptions

badRequest

If callback is invalid.

Samples

// iterates over all elements

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('VLAN');
contact.field('skills').each(function(skill, index) {
  log('skill: '+skill.label());
});

// iterate over the first two elements

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Java');
contact.field('skills').add('.NET');
contact.field('skills').add('Python');
contact.field('skills').add('Golang');
contact.field('skills').each(function(skill, index) {
  if (index > 1) {
      return false;
  }
  log('skill: '+skill.label());
});

get(index)

Retrieves the element at the specifed position.

Parameters

Name Type Required Default Description

index

number

yes

The position of the element to retrieve.

Returns

sys.data.Wrapper - Returns the wrapper of the element at the specified position.

Exceptions

badRequest

If index is invalid.

Samples

// gets an element from a position in the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+contact.field('skills').get(1).label());

first()

Retrieves the first element in the list.

Returns

sys.data.Wrapper - Returns the wrapper of the first element. null if list is empty.

Samples

// gets the first element in the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+contact.field('skills').first().label());

last()

Retrieves the last element in the list.

Returns

sys.data.Wrapper - Returns the wrapper of the last element. null if list is empty.

Samples

// gets the last element in the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('skills: '+contact.field('skills').last().label());

size()

Returns the number of elements in the list.

Returns

number - The number of elements in the list.

Samples

// counts the number of elements in the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
log('size: '+contact.field('skills').size());
contact.field('skills').add('WLAN');
log('size: '+contact.field('skills').size());
contact.field('skills').add('YouTube');
log('size: '+contact.field('skills').size());

contains(value)

Checks if the given value is already in the list, returning true when it is and false otherwise. In order to check if the value is on the list the method sys.data.Wrapper.equals() is used, which can be override by each type.

Parameters

Name Type Required Default Description

value

any

yes

The value to check if it is in the list. The type depends on the field.

Returns

boolean - true if value is in the list, false otherwise.

Exceptions

badRequest

If value is invalid. Validation rules depends on the type.

Samples

// checks if a value is in the list

var contact = sys.data.createRecord('contacts');
contact.field('skills').add('Firewalls');
contact.field('skills').add('WLAN');
contact.field('skills').add('YouTube');
log('Firewalls: '+contact.field('skills').contains('Firewalls'));
log('WLAN: '+contact.field('skills').contains('WLAN'));
log('YouTube: '+contact.field('skills').contains('YouTube'));
log('Java: '+contact.field('skills').contains('Java'));

sys.data.Action

When an action is executed, an object of this class will be available in the context of the scripts of the action with the name action. This allow access to fields in the action in a similar way to what you would do with record fields.

name()

Returns the name of the action being executed.

Returns

string - Name of the action being executed.

Samples

// print name of the action; only works inside scripts of an action

sys.logs.info('action being executed: '+action.name());

field(path)

Returns the action field at the given path. It works exactly the same as sys.data.Record.field() but it works over the fields defined on the action.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field. It could be a nested or multi-valued field.

Returns

sys.data.Wrapper or sys.data.ManyWrapper - A field object that you can use to read and manipulate the value.

Exceptions

badRequest

If path is invalid.

Samples

// logs the value of field 'param1'; only works inside a script of an action that has a 'param1' field

sys.logs.info('param1: '+action.field('param1').val());

sys.data.RecordHistoryLogs

Allows to query the history logs of a record. Keep in mind that the feature to log history must be enabled on the entity the record belongs to.

find(options)

Finds history logs based on a query.

Parameters

Name Type Required Default Description

options

object

no

This is the query to fetch history logs. Parameters are:

  • eventType: the type of the event. Possible values are: USER_RECORD_CREATED, USER_RECORD_CHANGED, USER_RECORD_DELETED, USER_ACTION_PERFORMED, SCRIPT_RECORD_CREATED, SCRIPT_RECORD_CHANGED, SCRIPT_RECORD_DELETED, SCRIPT_ACTION_PERFORMED, SYSTEM_CASCADE_UPDATE, SYSTEM_REFACTORING. You can specify many types separating them by commas.
  • from: the minimum timestamp in milliseconds from Epoch.
  • to: the maximum timestamp in milliseconds from Epoch.
  • size: the maximum number of logs to retrieve. Default 20.
  • offset: the offset to fetch more logs when paginating.

Returns

sys.data.RecordHistoryLog[] - The list of history logs.

Exceptions

badRequest

If the query is not valid.

Samples

// finds changes performed by users and logs the user that did it

var company = sys.data.findOne('companies', {name: 'Blogpad'});
var historyLogs = company.history().find({
  eventType: 'USER_RECORD_CHANGED'
});
for (var i = 0; i < historyLogs.length; i++) {
  var historyLog = historyLogs[i];
  log('changed by user: '+historyLog.user());
}

createLog()

Returns the create log of the record. It could be null if history log was not enabled when the record was created.

Returns

sys.data.RecordHistoryLog - The create history log or null if not found.

Samples

// prints who created the record

var company = sys.data.findOne('companies', {name: 'Blogpad'});
var createLog = company.history().createLog();
if (createLog) {
  log('creator: '+createLog.user());
}

lastModifiedLog()

Returns the last modified log of the record. It could be null if history log was not enabled when the record was modified for the last time or if it hasn’t been modified at all. The type of event should be USER_RECORD_CHANGE so if the record was modified by a script or by a system process it won’t be returned.

Returns

sys.data.RecordHistoryLog - The last modified history log or null if not found.

Samples

// prints who modified the record for the last time

var company = sys.data.findOne('companies', {name: 'Blogpad'});
var modifiedLog = company.history().lastModifiedLog();
if (modifiedLog) {
  log('user last modified: '+modifiedLog.user());
}

sys.data.RecordHistoryLog

Contains information about a history log of a record.

id()

Returns the ID of the history log

Returns

string - The ID of the history log

timestamp()

Returns the date in which the history log has been recorded.

Returns

Date - The date in which log has been recorded

eventCategory()

Returns the event category of the history log. It could be USER, SCRIPT, or SYSTEM.

Returns

string - The event category of the history log.

eventType()

Returns the event type of the history log. It could be USER_RECORD_CREATED, USER_RECORD_CHANGED, USER_RECORD_DELETED, USER_ACTION_PERFORMED, SCRIPT_RECORD_CREATED, SCRIPT_RECORD_CHANGED, SCRIPT_RECORD_DELETED, SCRIPT_ACTION_PERFORMED, SYSTEM_CASCADE_UPDATE, SYSTEM_REFACTORING

Returns

string - The event type of the history log.

user()

Returns the email of the user that generated the history log.

Returns

string - The email of the user that generated the history log.

ip()

Returns the IP of the user when the history log was generated.

Returns

string - The IP of the user when the history log was generated.

oldRecord()

Returns the old values of the fields that were modified. On each field it will contain the JSON format as well as a more human-redable format. Here is a sample:

{
  "type": {
    "json": "a",
    "text": "{type:a}"
  }
}

Returns

object - The old values of the fields that were modified.

newRecord()

Returns the new values of the fields that were modified. On each field it will contain the JSON format as well as a more human-redable format. Here is a sample:

{
  "type": {
    "json": "a",
    "text": "{type:a}"
  }
}

Returns

object - The new values of the fields that were modified.

sys.data.Query

Allows to build more complex quieries easily. Here you will find information about the methods provided by this class. If you want to understand how to use and write queries, please check the documentation on Query language.

Usually you will create query objects using the method sys.data.createQuery() instead of using the constructor directly.

field(path)

Returns a sys.data.QueryField object for the given field. With this object you can add filters to the field.

Please check Filter by field for more information on how it works.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field. It could be a nested or multi-valued field.

Returns

sys.data.QueryField - A field object for the given path.

Exceptions

badRequest

If path is invalid.

Samples

// print the name of 10 active companies

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('state');
queryField.equals('active');
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

// this is the same as the sample above, but using a more compact format

// create a new sys.data.Query object
var query = sys.data.createQuery('companies')
    .field('state').equals('active')
    .size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

size(size)

Sets the maximum number of records to be retrieved.

Please check Limit size for more information on how it works.

Parameters

Name Type Required Default Description

size

number

yes

Maximum number of records to be retrieved.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If it is not a number.

Samples

// print the name of 10 companies

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

offset(size)

Sets the number of records to be skipped.

Please check Skip records for more information on how it works.

Parameters

Name Type Required Default Description

size

number

yes

Maximum number of records to be retrieved.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If it is not a number or string.

Samples

// print the name of 10 companies

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

sortBy(sortField, sortType)

Sets the field and direction to sort results.

Please check Sorting for more information on how it works.

Parameters

Name Type Required Default Description

sortField

string

yes

The path of the field to be used for sorting.

sortType

string

yes

Sort direction. Possible values are asc and desc.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If sortField is not a valid path or sortType is different from asc or desc.

Samples

// print the name of the first 10 companies sorted by name

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.sortBy('name', 'asc');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

includeFields(paths)

Allows to select which fields should be fetched.

Please check Select fields to fetch for more information on how it works.

Parameters

Name Type Required Default Description

paths

string...

yes

The path of the fields that have to be fetched.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If any of the paths provided is not a valid field.

Samples

// only name and email fields will be fetched

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.includeFields('name', 'type');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

globalSearch(value)

Tries to match the string in any field on the entity instead of trying to match one specific field. Notice that in order to match the whole sentence you need to enclose it with double quotes. This is only allowed for entities with global search enabled.

Please check Global search for more information on how it works.

Parameters

Name Type Required Default Description

value

string

yes

The value to search globally.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If value is not a string.

Samples

// finds records where any field has either the word 'lacinia'' or 'erat'

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.globalSearch('lacinia erat');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

query(complexQueryOrFunction)

Allows to specify a complex query where it is possible to mix AND and OR expressions.

Please check Complex queries for more information on how it works.

Parameters

Name Type Required Default Description

complexQueryOrFunction

function or string

yes

A string representing a complex query or an anonymous function returning a sys.data.ComplexQueryCriteria.

Returns

sys.data.Query - The same query object. This is to allow to chain more operations easily.

Exceptions

badRequest

If the query is invalid.

Samples

// finds companies with type 'a' or with type 'b' where they are also customers

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.query(function(q) {
  return q.or(
    q.field('type').equals('a'),
    q.and(
      q.field('type').equals('b'),
      q.field('isCustomer').equals(true)
    )
  );
});
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

// same query as above, but using a complex query string instead

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
query.query("or(filter('type','a'),and(filter('type','b'),filter('isCustomer','true')))");
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

sys.data.QueryField

This object is returned by the method sys.data.Query.field() and allows to apply filters to the field.

Please check Filters by field for more information on filter data.

equals(value)

Adds a filter using equals operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of 10 active companies

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('state');
queryField.equals('active');
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

notEquals(value)

Adds a filter using not equals operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of 10 companies where type is not 'a'

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('type');
queryField.notEquals('a');
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

empty()

Adds a filter using empty operator.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type.

Samples

// print the name of companies where notes are empty

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('notes');
queryField.empty();
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

notEmpty()

Adds a filter using not empty operator.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type.

Samples

// print the name of 10 companies where notes are not empty

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('notes');
queryField.notEmpty();
query.size(10);
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

like(value)

Adds a filter using like operator. This filter type has support for regular expressions and also provide shortcuts for filtering by starts with and ends with.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies where name contains 'odo'

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('name');
queryField.like('odo');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

// print the name of companies where name starts with 't', can have something else in the middle and ends with 'e' using a regular expression

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('name');
queryField.like('/^t.*e$/');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

// print the name of companies where name starts with 't' using the `starts with` shortcut

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('name');
queryField.like('/t');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

// print the name of companies where name ends with 'e' using the `ends with` shortcut

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('name');
queryField.like('e/');
var records = sys.data.find(query);
while (records.hasNext()) {
  log(records.next().label());
}

greater(value)

Adds a filter using greater operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies with more than 500 employees

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('numberOfEmployees');
queryField.greater(500);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

greaterOrEquals(value)

Adds a filter using greater or equals operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies with more than 500 employees or exactly 500 employees

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('numberOfEmployees');
queryField.greaterOrEquals(500);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

less(value)

Adds a filter using less operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies with less than 500 employees

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('numberOfEmployees');
queryField.less(500);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

lessOrEquals(value)

Adds a filter using less or equals operator.

Parameters

Name Type Required Default Description

value

any

yes

The value to compare to. Please check the field’s type documentation to see which values are allowed.

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies with less than 500 employees or exactly 500 employees

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('numberOfEmployees');
queryField.lessOrEquals(500);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

between(from, to)

Adds a filter using between operator.

Parameters

Name Type Required Default Description

from

any

yes

The minimum value to match (inclusive).

to

any

yes

The maximum value to match (inclusive).

Returns

sys.data.Query or sys.data.QueryField - Returns the sys.data.Query object to allow chain operations or a sys.data.QueryField in case you are using it in a complex query.

Exceptions

badRequest

If operation is not supported for the field’s type or if the value is not valid for this type. Keep in mind that some invalid values might be detected only once the query is executed.

Samples

// print the name of companies with a number of employees between 300 and 600 (inclusive)

// create a new sys.data.Query object
var query = sys.data.createQuery('companies');
var queryField = query.field('numberOfEmployees');
queryField.between(300, 600);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

sys.data.ComplexQueryHelper

This object is passed as a parameter to the function passed in the method sys.data.Query.query() and helps to build a complex query with AND and OR operators.

Please check Complex queries for more information.

field(path)

Returns an sys.data.QueryField object for the given field. With this object you can add filters to the field.

Please check Filter by field for more information on how it works.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field. It could be a nested or multi-valued field.

Returns

sys.data.QueryField - A query field object for the given path.

Exceptions

badRequest

If path is invalid.

Samples

// print the name of 10 companies of type 'a'

var query = sys.data.createQuery('companies')
    .query(function(q) {
      // 'q' is an object of type sys.data.QueryComplexHelper
      return q.and(
        q.field('type').equals('a')
      );
    })
    .size(10);
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

and(conditions)

Returns a sys.data.ComplexQueryCriteria object to do an AND with the given parameters.

Please check Complex queries for more information.

Parameters

Name Type Required Default Description

conditions

sys.data.QueryField or sys.data.ComplexQueryCriteria

yes

Any number of query fields or other complex query criteria (like an OR) that will be evaluated using the AND operator.

Returns

sys.data.ComplexQueryCriteria - A complex query criteria object with an AND between all parameters.

Exceptions

badRequest

If parameters sent to the AND operator are invalid.

Samples

// print the companies where tyep is 'a' or where type is 'b' and are customers

var query = sys.data.createQuery('companies')
    .query(function(q) {
      // 'q' is an object of type sys.data.QueryComplexHelper
      return q.or(
        q.field('type').equals('a'),
        q.and(
          q.field('type').equals('b'),
          q.field('isCustomer').equals(true)
        )
      );
    });
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

or(conditions)

Returns a sys.data.ComplexQueryCriteria object to do an OR with the given parameters.

Please check Complex queries for more information.

Parameters

Name Type Required Default Description

conditions

sys.data.QueryField or sys.data.ComplexQueryCriteria

yes

Any number of query fields or other complex query criteria (like an AND) that will be evaluated using the OR operator.

Returns

sys.data.ComplexQueryCriteria - A complex query criteria object with an OR between all parameters.

Exceptions

badRequest

If parameters sent to the OR operator are invalid.

Samples

// print the companies where tyep is 'a' or where type is 'b' and are customers

var query = sys.data.createQuery('companies')
    .query(function(q) {
      // 'q' is an object of type sys.data.QueryComplexHelper
      return q.or(
        q.field('type').equals('a'),
        q.and(
          q.field('type').equals('b'),
          q.field('isCustomer').equals(true)
        )
      );
    });
var records = sys.data.find(query);
log('total: '+records.count());
while (records.hasNext()) {
  log(records.next().label());
}

sys.data.ComplexQueryCriteria

This object is returned by the method in sys.data.ComplexQueryHelper. You shouldn’t use this object directly.

Please check Complex queries for more information.

toString()

Returns the string version of the complex query.

Returns

string - The string version of the complex query

sys.data.AggregateQuery

Allows to build aggregate quieries easily. Here you will find information about the methods provided by this class. If you want to understand how to use and write aggregate queries, please check the documentation on Aggregate queries.

Usually you will create query objects using the method sys.data.createAggregateQuery() instead of using the constructor directly.

group()

Adds a sys.data.AggregatedGroup operation to the aggregate query.

Please check Group for more information on how to use it.

Returns

sys.data.AggregatedGroup - The group object added to the aggregate query.

match()

Adds a sys.data.AggregatedMatch operation to the aggregate query.

Please check Match for more information on how to use it.

Returns

sys.data.AggregatedMatch - The match object added to the aggregate query.

sort()

Adds a sys.data.AggregatedSort operation to the aggregate query.

Please check Sort for more information on how to use it.

Returns

sys.data.AggregatedSort - The sort object added to the aggregate query.

project()

Adds a sys.data.AggregatedProject operation to the aggregate query.

Please check Project for more information on how to use it.

Returns

sys.data.AggregatedProject - The project object added to the aggregate query

count()

Adds a sys.data.AggregatedCount operation to the aggregate query.

Please check Count for more information on how to use it.

Returns

sys.data.AggregatedCount - The count object added to the aggregate query

skip()

Adds a sys.data.AggregatedSkip operation to the aggregate query.

Please check Skip for more information on how to use it.

Returns

sys.data.AggregatedSkip - The skip object added to the aggregate query

limit()

Adds a sys.data.AggregatedLimit operation to the aggregate query.

Please check Limit for more information on how to use it.

Returns

sys.data.AggregatedLimit - The limit object added to the aggregate query

unwind()

Adds a sys.data.AggregatedUnwind operation to the aggregate query.

Please check Unwind for more information on how to use it.

Returns

sys.data.AggregatedUnwind - The unwind object added to the aggregate query

lookup()

Adds a sys.data.AggregatedLookup operation to the aggregate query.

Please check Lookup for more information on how to use it.

Returns

sys.data.AggregatedLookup - The lookup object added to the aggregate query

sys.data.AggregatedGroup

Allows to define a group operation in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.group() method.

Please check the documentation on Group for more information on how to use the group operator.

by(paths)

Indicates which fields will be used to group by.

Parameters

Name Type Required Default Description

paths

string...

yes

The path of the fields used for grouping.

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If any of the paths is invalid.

accumulate(path)

Allows to apply an operation for the values in the group for a given field. For example, sum all values in the group or calculate the average.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to apply the operation to

Returns

sys.data.AggregateAccumulator - The accumulator object to configure the operation to perform.

Exceptions

badRequest

If the paths is invalid.

Samples

// 

var query = sys.data.createAggregateQuery('contacts');
query.group()
    .by('company')
    .accumulate('totalSkills').sum('numberOfSkills');
var resultSet = sys.data.aggregate(query);
while (resultSet.hasNext()) {
  log(JSON.stringify(resultSet.next()));
}

sys.data.AggregatedSort

Allows to sort elements in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.sort() method.

Please check the documentation on Sort for more information on how to use the sort operator.

by(path, sortType)

Indicates which field will be used to sort and the direction of the sorting.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field used for sorting.

sortType

string

yes

The direction of the sorting. Can be asc or desc.

Returns

sys.data.AggregatedSort - The sort object so you can chain more operations.

Exceptions

badRequest

If the path or direction are invalid.

sys.data.AggregatedProject

Allows to filter fields in elements in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.project() method.

Please check the documentation on Project for more information on how to use the project operator.

field(path)

Indicates that the given field should be included in the result.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to include in the results.

Returns

sys.data.AggregatedProject - The project object so you can chain more operations.

Exceptions

badRequest

If the path is invalid.

sys.data.AggregatedMatch

Allows to filter elements by a query in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.match() method.

Please check the documentation on Match for more information on how to use the match operator.

field(path)

Indicates that the given field should be included in the result.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to apply a filter to.

Returns

sys.data.QueryField - The match object so you can apply filters on that field.

Exceptions

badRequest

If the path is invalid.

sys.data.AggregateAccumulator

Allows to define accumulation operations for groups created using sys.data.AggregatedGroup like sum, average, etc.

Please check the documentation on Group for more information on how to use aggregations.

sum(path)

Sums all the numeric values in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to sum up

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

count()

Counts the number of elements in the group.

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

avg(path)

Calculates the average of all the numeric values in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to calculate average

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

first(path)

Selects the value of the first element in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to select its value

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

last(path)

Selects the value of the last element in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to select its value

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

min(path)

Selects the minimum value in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to select its minimum value

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

max(path)

Selects the maximum value in the group for the given field.

Parameters

Name Type Required Default Description

path

string

yes

The path of the field to select its maximum value

Returns

sys.data.AggregatedGroup - The group object so you can chain more operations.

Exceptions

badRequest

If the path is invalid or not a numeric field.

sys.data.AggregatedCount

Allows to count elements in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.count() method.

Please check the documentation on Count for more information on how to use the count operator.

counterName(fieldName)

Indicates that the given string should be the name of attribute under counter will be stored.

Parameters

Name Type Required Default Description

fieldName

string

yes

The name of field that will store the counter.

Returns

sys.data.AggregatedCount - The count object so you can chain more operations.

Exceptions

badRequest

If the fieldName is invalid.

sys.data.AggregatedLimit

Allows to limit the number of elements in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.limit() method.

Please check the documentation on Limit for more information on how to use the limit operator.

step(number)

Indicates that first step number of elements will be retrieved.

Parameters

Name Type Required Default Description

number

number

yes

The positive interger number of records to ommit.

Returns

sys.data.AggregatedLimit - The limit object so you can chain more operations.

Exceptions

badRequest

If the number is invalid.

sys.data.AggregatedSkip

Allows to skip elements in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.skip() method.

Please check the documentation on Skip for more information on how to use the skip operator.

step(number)

Indicates that first step number of elements will not be retrieved.

Parameters

Name Type Required Default Description

number

number

yes

The positive interger number of records to ommit.

Returns

sys.data.AggregatedSkip - The skip object so you can chain more operations.

Exceptions

badRequest

If the number is invalid.

sys.data.AggregatedUnwind

Allows to unwind elements with array attributes in more elements with single attributes in an aggregate query. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.unwind() method.

Please check the documentation on Unwind for more information on how to use the unwind operator.

path(fieldPath)

Indicates selected attribute will be unwound in single elements retrieving one document by every item in array value.

Parameters

Name Type Required Default Description

fieldPath

string

yes

Field in record to be unwound.

Returns

sys.data.AggregatedUnwind - The unwind object so you can chain more operations.

Exceptions

badRequest

If the fieldPath is invalid.

includeEmpty(includeEmpty)

Indicates that elements with selected attribute equals to empty array or null will be included.

Parameters

Name Type Required Default Description

includeEmpty

boolean

no

if true includes records for empty arrays, nulls or not multivalued fields.

Returns

sys.data.AggregatedUnwind - The unwind object so you can chain more operations.

sys.data.AggregatedLookup

Allows to lookup elements with other collections elemtents making an equivalent SQL left join. You should never create an object of this class manually. Instead use sys.data.AggregateQuery.lookup() method.

Please check the documentation on Lookup for more information on how to use the lookup operator.

localField(fieldPath)

Indicates selected attribute from current entity elements that will be matched with foreign elements.

Parameters

Name Type Required Default Description

fieldPath

string

yes

Field into current entity used as local field.

Returns

sys.data.AggregatedLookup - The lookup object so you can chain more operations.

Exceptions

badRequest

If the fieldPath is invalid.

foreignField(fieldPath)

Indicates selected attribute from foreign entity elements that will be matched with current elements.

Parameters

Name Type Required Default Description

fieldPath

string

yes

Field into foreign entity used as foreign field.

Returns

sys.data.AggregatedLookup - The lookup object so you can chain more operations.

Exceptions

badRequest

If the fieldPath is invalid.

foreignEntity(entityName)

Indicates the foreign entity name whose elements will be matched.

Parameters

Name Type Required Default Description

entityName

string

yes

Name of an existing entity.

Returns

sys.data.AggregatedLookup - The lookup object so you can chain more operations.

Exceptions

badRequest

If the entityName is invalid.

Back to top