If there’s one SuiteScript module you’ll use in almost every script you write, it’s the N/search module. Whether you’re pulling a list of open invoices, finding all items below reorder level, or checking whether a customer already exists β the N/search module is how you query data in NetSuite programmatically.
This guide covers everything you need to know about the N/search module: how it works, the different ways to run searches, how to handle results, and real-world patterns that will save you hours of debugging.
What Is the N/search Module?
The N/search module is a SuiteScript 2.x module that allows you to run saved searches and ad-hoc searches programmatically against any record type in NetSuite. It replaces the old nlapiSearchRecord() function from SuiteScript 1.0 with a much cleaner, more powerful API.
You can use N/search to:
Search any NetSuite record type (customers, invoices, items, employees, and more)
Filter results using conditions (AND / OR logic)
Return specific columns and joined fields
Load and re-run existing saved searches
Page through large result sets efficiently
How to Require the N/search Module
Before you can use any N/search functions, you need to require the module in your SuiteScript 2.x script:
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/search'], function(search) {
// Your script logic here
});
Creating an Ad-Hoc Search with search.create()
The most common way to search records is by building a search on the fly using search.create(). You define the record type, add filters and columns, then run it.
// Search for all open Sales Orders
var mySearch = search.create({
type: search.Type.SALES_ORDER,
filters: [
search.createFilter({
name: 'status',
operator: search.Operator.ANYOF,
values: ['SalesOrd:A', 'SalesOrd:B', 'SalesOrd:D'] // Pending Approval, Pending Fulfillment, Partially Fulfilled
})
],
columns: [
search.createColumn({ name: 'tranid' }),
search.createColumn({ name: 'entity' }),
search.createColumn({ name: 'amount' }),
search.createColumn({ name: 'trandate' })
]
});
mySearch.run().each(function(result) {
var orderId = result.getValue('tranid');
var customer = result.getText('entity');
var amount = result.getValue('amount');
log.debug('Open Order', orderId + ' | ' + customer + ' | $' + amount);
return true; // continue to next result
});
Loading an Existing Saved Search with search.load()
If you’ve already built a search in the NetSuite UI and saved it, you can load and run it directly in SuiteScript using search.load(). This is a great pattern when business users want to manage the search criteria themselves without needing a script change.
// Load a saved search by its internal ID (found in the URL when viewing the saved search)
var savedSearch = search.load({
id: 'customsearch_open_invoices_report'
});
savedSearch.run().each(function(result) {
var invoiceId = result.getValue('tranid');
var amountDue = result.getValue('amountremaining');
var dueDate = result.getValue('duedate');
log.debug('Overdue Invoice', invoiceId + ' | Due: $' + amountDue + ' | Date: ' + dueDate);
return true;
});
Handling Large Result Sets with getRange()
The .run().each() pattern works well for up to 4,000 results. But when you need to handle large data sets β or need the total count β use search.ResultSet.getRange() or pagedData.fetch().
// Use getRange to retrieve results in batches (0-based index)
var resultSet = mySearch.run();
var results = resultSet.getRange({ start: 0, end: 1000 });
results.forEach(function(result) {
var name = result.getValue('entityid');
log.debug('Record', name);
});
// For very large datasets, use pagedData (up to 1000 per page)
var pagedData = mySearch.runPaged({ pageSize: 1000 });
pagedData.pageRanges.forEach(function(pageRange) {
var page = pagedData.fetch({ index: pageRange.index });
page.data.forEach(function(result) {
var id = result.id;
var name = result.getValue('entityid');
log.debug('Paged Result', id + ': ' + name);
});
});
Using getValue() vs getText()
One of the most common sources of confusion in N/search is knowing when to use getValue() versus getText(). Here’s the simple rule:
getValue() returns the internal ID or raw value stored in the field (e.g., “1234”, “T”, “CustJob:A”)
getText() returns the human-readable display label (e.g., “Acme Corp”, “Yes”, “Customer/Project”)
For list/select fields like Customer, Status, or Subsidiary β always use getText() when you need the label shown in the UI.
N/search Best Practices & Common Pitfalls
Here are the most important tips to keep in mind when using N/search in your daily development work:
- Always return true in .each() β if you forget, the loop stops after the first result.
- 2. Watch for usage limits β N/search counts against your script’s governance units. Each page of results uses units, so be mindful in Map/Reduce and Scheduled scripts.
- 3. Use search.Type constants β instead of hardcoding strings like ‘salesorder’, use search.Type.SALES_ORDER for safety and autocomplete support.
- 4. Prefer saved searches for complex logic β if your filter logic involves many conditions or joins, build it as a saved search in the UI and load it with search.load(). It’s easier to maintain and test.
- 5. Use search.Operator constants β operators like search.Operator.IS, search.Operator.ANYOF, and search.Operator.GREATERTHAN make your code self-documenting and less error-prone.
- 6. Don’t run searches inside loops β running a search inside a forEach or .each() creates N+1 problems and burns governance fast.
Final Thoughts
The N/search module is easily the most used SuiteScript module in daily NetSuite development. Whether you’re writing a simple client script to validate a customer’s outstanding balance or a complex scheduled script that processes thousands of transactions overnight, N/search is at the core of it all.
Mastering the patterns covered in this guide β search.create(), search.load(), .run().each(), getRange(), and runPaged() β will give you the tools to handle virtually any data retrieval task in NetSuite with confidence.
Have a specific search use case you’re stuck on? Drop a question in the community below β we’d love to help!
Discover more from The NetSuite Pro
Subscribe to get the latest posts sent to your email.
Leave a Reply