Sign up to receive SuiteScript examples and advice directly in your email inbox.

9 Introduction to Searching with SuiteScript 2.0

Created: June 26, 2017

In this edition, we start looking at how to transition our Searches from SuiteScript 1.0 over to 2.0. This is quite an important and lengthy concept in SuiteScript, so we'll be exploring Searching over several weeks.

To coincide with this series of articles on Searching, I have also created a series of SuiteScript cookbooks focused on Searching. These cookbooks are intended to provide you with reference examples for the most common Searching concepts and techniques.

N/search Module

In SuiteScript 1.0, there were two separate APIs for performing Searches. The first was the nlapiSearchRecord method that would create the Search, execute the Search, and return the results all in one call. The second API broke the creation, execution, and results retrieval into separate method calls.

In SuiteScript 2.0, all searching capabilities are provided by the N/search module. The N/search module API mimics that of the latter API from 1.0.

Search API Equivalencies between SuiteScript 1.0 and 2.0

There is no direct 2.0 equivalent for nlapiSearchRecord.

In SuiteScript 2.0, you will be creating or loading the Search, executing the Search, and retrieving the results all with separate method calls.

To start, let's investigate an example of loading and executing a Saved Search. We'll start with a very simple Saved Search that shows all Employees hired in the current year.

// 1.0
var search = nlapiLoadSearch("employee", "customsearch_emp_hiredthisyear");
var resultSet = search.runSearch(); 
// 2.0 - Console
require(["N/search"], function (s) {
    var search = s.load({id: "customsearch_emp_hiredthisyear"});
    var resultSet = search.run();
}); 

In 1.0, we leverage nlapiLoadSearch to obtain a reference to the Saved Search, then we call its runSearch method to execute the Search on the server.

The 2.0 version of this same functionality looks very similar. We begin by calling the Search module's load method, then calling the run method on the Search reference to execute it on the server.

Notice also that we're not declaring any specific Script module with the define function; instead, we're using the require function so that you can paste this code directly into your browser console or the NetSuite debugger environment.

Iterating through Results

From here, in 1.0, there were two different ways we could retrieve our results for processing. The first was by using the forEachResult iterator method.

// 1.0
var search = nlapiLoadSearch("employee", "customsearch_emp_hiredthisyear");
var resultSet = search.runSearch();
resultSet.forEachResult(printEmployeeName);

function printEmployeeName(result) {
    nlapiLogExecution("DEBUG", "Employee Name:", result.getValue("firstname"));
    return true;
}
// 2.0 - Console
require(["N/search"], function (s) {
    var search = s.load({id: "customsearch_emp_hiredthisyear"});
    var resultSet = search.run();
    resultSet.each(printEmployeeName);

    function printEmployeeName(result) {
        log.debug({title: "Employee Name:", details: result.getValue({name: "firstname"})});
        return true;
    }
}); 

2.0 offers an equivalent to the forEachResult iterator: the each iterator. Just as in 1.0, the 2.0 each iterator will run through at most 4000 results; your callback function must return a Boolean value:

  • true to continue iterating;
  • false to stop

If you're using each, and you can't figure out why your Script is only processing one result, please check that your callback method is returning the appropiate boolean value. I have seen this question over and over; don't say I didn't warn you!

The getRange Iterator

Our other option in 1.0 was the getResults method that would retrieve a very specific chunk of the result set.

// 1.0 
var search = nlapiLoadSearch("employee", "customsearch_emp_hiredthisyear");
var resultSet = search.runSearch();
var results = resultSet.getResults(0, 1000);
for (var i = 0; i < results.length; i++) {
    printEmployeeName(results[i]);
}

function printEmployeeName(result) {
    nlapiLogExecution("DEBUG", "Employee Name:", result.getValue("firstname"));
} 
// 2.0 - Console
require(["N/search"], function (s) {
    var search = s.load({id: "customsearch_emp_hiredthisyear"});
    var resultSet = search.run();
    var results = resultSet.getRange({start: 0, end: 1000});
    for (var i = 0; i < results.length; i++) {
        printEmployeeName(results[i]);
    }

    function printEmployeeName(result) {
        log.debug({title: "Employee Name:", details: result.getValue({name: "firstname"})});
    }
}); 

Once again, 2.0 offers a corresponding method called getRange. We provide getRange with the starting and ending index of the results we want to retrieve. The slice of results can be from any part of the entire set, but is limited to a maximum of 1000 results per call to getRange.

Method Chaining

Now I've been fairly explicit with our method calls here, assigning each one to a variable output; however, as with most 2.0 APIs, we can chain our Search API calls to make our code a bit more concise:

require(["N/search"], function (s) {
    s.load({
        id: "customsearch_emp_hiredthisyear"
    }).run().each(printEmployeeName);

    function printEmployeeName(result) {
        log.debug({
            title: "Employee Name:",
            details: result.getValue({name: "firstname"})
        });
        return true;
    }
});

We can chain all of our calls to load, run, and each together; we could also chain getRange in exactly the same way.

We have barely scratched the surface of Searches in SuiteScript 2.0; if you're looking to accelerate your mastery of searching in SuiteScript, make sure you check out the SuiteScript Cookbooks.