How to use pagination and sorting when searching for app items

Sorting allows you to place the elements of the search results array in ascending or descending order based on the values of one of the app item’s properties. For example, you can place all items of the Employees app in ascending order of employees’ age (based on the Age variable of the Number type in the app).

The Search.sort method receives two arguments. The first one is the code of the app property that is used for sorting (note that the Search and sort by field option needs to be enabled in the property’s settings). The second argument of the Boolean type defines whether the results need to be displayed in ascending order. If the value doesn’t evaluate to true, the system will place the results in descending order.

const employees = await Context.fields.employee.app.search().sort('age',true).size(10000).all();

Pagination is used to split the list of all search results into separate parts. This may be needed, for instance, if these results have to be processed in a script that runs for a long period of time. To avoid a situation where the timeout expires before all items are processed, you can pass them to the script in chunks.

Pagination is also needed when more than 10,000 app items need to be processed, as this is the largest number of results that the search() method can return.

Let’s say the process consists of two Script activities.

The Script calculating the number of items activity includes a script that calculates the total number of app items to be processed and sets the starting value of the counter:

const counter = await Namespace.app.contracts.search().count();
Context.data.total = counter;
Context.data.str = counter.toString()+ \" found total\";
Context.data.work_element = 0;

In this script:

  • contracts is the name of the app that we work with.
  • counter and Context.data.total store the total number of app items that need to be processed.
  • Context.data.work_element is a variable of the Number type; it’s a counter for items that search will be applied to.
  • Context.data.str is a variable of the String type that displays the number of items found.

The second activity, Loading and processing the next 50 items, includes a script that is used to process one “chunk” of items:

const batch  = await Namespace.app.contracts.search().from(Context.data.work_element!).size(50).all();

/* Let’s declare a variable that will make it possible to save all items at once
without using asynchronous calls inside a loop */
let promises: Promise<void> [] = [];

for (let item of batch)
\t{
\t\titem.data.string = \"Done\";
\t\tpromises.push(item.save());
\t}

// Saving all changed items
await Promise.all(promises); 

Context.data.work_element = Context.data.work_element! + 50;

In this script, string is a property of the contracts app (the one that we need to change).

After the second script, there is a gateway. By default, it returns the process to the previous step to work with the next 50 items. This keeps happening until the condition work_element >= complete is met, which means that the number of processed items is equal or larger than the total number of items found in the app during search.