How to limit search result in SuiteScript (1 or 2)? - netsuite

Is there a way to limit the amount of records returned via SuiteScript? I use the following method, but the search still gets all results. I am breaking out of the iteration of the results if I've hit the max I'd like to return. I can't find anything in the documentation.
In the UI it looks like one can limit the returned results, even though I haven't had much luck with it. (Maybe because I'm joining...)
var accountSearch = search.create({
type: search.Type.CUSTOMER,
columns: searchColumns,
filters: searchFilters
});
var searchResultsPagedData = accountSearch.runPaged({
'pageSize': 1000
});
var max = 9;
for (var pageIndex = 0; pageIndex < searchResultsPagedData.pageRanges.length; pageIndex++) {
var pageRange = searchResultsPagedData.pageRanges[pageIndex];
if (pageRange.index >= max)
break;
var searchPage = searchResultsPagedData.fetch({ index: pageRange.index });
// Iterate over the list of results on the current page
searchPage.data.forEach(function (result) {
}
}

Use getRange instead of each to iterate over your results. getRange lets you specify a start and end index to grab a specific slice of the results.

Why not just set the page size to the max number of results you want and only iterate over the first page (page 0)? Or if you're looking for more than 1000 results you could limit the number of pages by setting pageIndex < max; instead of pageIndex < searchResultsPagedData.pageRanges.length;

Another approach: from the comments it seems one of the issues you're having is running into the execution limit, so you could load the N/runtime module and use Script.getRemainingUsage() before each fetch to ensure you have enough governance units left - and break or return if you don't.

Related

is there any way to show more than 1000 sublist lines in SuiteLet NetSuite?

i have created a suitelet with sublist showing the results of saved search (1000+ results).
Is there any way to show more than 1000 lines in sublists of suitelet as my search has more than 1000 lines?
Without any of your code I cannot give you anything specific, but I can give you an example of how you would pull more than 1,000 lines/results from a saved search in SuiteScript.
The .run() method has a limit of 4,000 records I believe, so it could work, but I've been using the .runPaged() method to pull 10,000+ results from some of my saved searches.
let sObj = search.load({id: SEARCH_ID,type: SEARCH_TYPE}),
holdres = [];
let pd = sObj.runPaged({pageSize: 1000});
for(let i = 0; i < pd.pageRanges.length; i++) {
let cp = pd.fetch(i);
cp.data.forEach(r => {
let ri = {};
r.columns.forEach(col => {
ri[col["name"]] = r.getValue({name: col["name"]});
});
holdres.push(ri);
});
}
console.log(holdres);
This example pulls 1,000 records at a time, but will continue to pull results and loop through them (1,000 at a time). Then it just stores them in an array and uses the field names from NetSuite.

How to filter large array based on "in-between" value in a sub-array? (Node.js)

I have a large database of items that have somewhat fluid statuses. I need to get an array of those items based on what each items's status was on a given date.
Here's an excerpt from an example record:
{"status":[
{"date":{"$date":"2019-06-14T06:17:41.625Z"},"statusCode":200},
{"date":{"$date":"2019-11-04T02:02:58.020Z"},"statusCode":404},
{"date":{"$date":"2020-08-07T01:11:16.184Z"},"statusCode":200},
{"date":{"$date":"2020-08-07T03:54:09.703Z"},"statusCode":404}
]}
Using this example, the status on 2020-01-13 would be 404 (as it would be also on 2020-01-12 or any other givenDate until the status changed back to 200).
So how would I filter my big array to this record (and others like it) to only items with status 404 as of 2020-01-13? (And I would do the same for 200.)
Note that I can't simply filter for objects with date < givenDate && statusCode == 200 because that would ignore if the status changed after those records. (The above example would return for either 200 or 404 since both records exist before givenDate.)
My only idea at the moment is that I could first filter the status array to anything before givenDate, and then compare based on the last record (since this filtered array's last record would then always be before givenDate). But this seems more complicated than necessary.
Processing time isn't important to me on this because I'm trying to make some one-time corrections to past statistics.
Thanks in advance!
A bit verbose, but I think this should do what you want.
var feedHistory = {"status":[
{"date":{"$date":"2019-06-14T06:17:41.625Z"},"statusCode":200},
{"date":{"$date":"2019-11-04T02:02:58.020Z"},"statusCode":404},
{"date":{"$date":"2020-08-07T01:11:16.184Z"},"statusCode":200},
{"date":{"$date":"2020-08-07T03:54:09.703Z"},"statusCode":404}
]};
const filterByStatus = (feedHistory,statusDate) => {
let foundRecord = false;
feedHistory.forEach((record) => {
let recordDate = new Date(Date.parse(record.date['$date']));
if (recordDate < statusDate && (!foundRecord || foundRecord.parsedDate < recordDate)) {
record.parsedDate = recordDate;
foundRecord = record;
}
});
return foundRecord;
};
var statusDate = new Date('2019-06-15');
var statusOnDate = filterByStatus(feedHistory.status,statusDate);
console.log(`On ${statusDate} the status was ${statusOnDate.statusCode}`);

Querying a 4000 rows list in SharePoint is slow as hell

I just want to fetch a list of items from the SiteUserInfoList list. This list holds roughly 4000 rows.
var watch = System.Diagnostics.Stopwatch.StartNew();
var qry = new SPQuery { Query = "<Where><Eq><FieldRef Name='ContentType'/><Value Type='Text'>MyValue</Value></Eq></Where>" };
var list = new List<Entity>();
using (var web = spSite.OpenWeb())
{
var groups = web.SiteUserInfoList.GetItems(qry);
foreach (SPListItem group in groups)
{
list.Add(new Entity
{
Id = group.ID,
Guid = group.UniqueId,
Title = group.Title
});
}
}
watch.Stop();
Console.Write(watch.ElapsedMilliseconds);
ElapsedMilliseconds gets an average of 20 seconds! How can that be so long?! (Server is a Xeon W-2145 that is shared for multiple VMs but still - CPU usage never goes beyond 20%)
I also tried:
fetching the entire list and filtering it in the code. It is a little bit faster (15 sec)
ContentType Indexed property is false (computed value based on ContentTypeId), but ContentTypeId is true. (So I assume ContentType is indexed somehow?)
fetching the results with RowLimit. Got the best results with RowLimit = 5000 (?!). (tried 100, 1000, 2000, ...8000): 6 sec, still too long!
Any idea? Please help optimizing :)
Thank you.
Ok I found out that there is ContentTypesEnabled property that was set to false.
Don't really know what is behind this property as it is not well documented.
And I cannot set it back to false...
When I set it to true I'm now under 2 secs!

Get actual count of matches in Azure Search

Azure Search returns a maximum of 1,000 results at a time. For paging on the client, I want the total count of matches in order to be able to display the correct number of paging buttons at the bottom and in order to be able to tell the user how many results there are. However, if there are over a thousand, how do I get the actual count? All I know is that there were at least 1,000 matches.
I need to be able to do this from within the SDK.
If you want to get total number of documents in an index, one thing you could do is set IncludeTotalResultCount to true in your search parameters. Once you do that when you execute the query, you will see the count of total documents in an index in Count property of search results.
Here's a sample code for that:
var credentials = new SearchCredentials("account-key (query or admin key)");
var indexClient = new SearchIndexClient("account-name", "index-name", credentials);
var searchParameters = new SearchParameters()
{
QueryType = QueryType.Full,
IncludeTotalResultCount = true
};
var searchResults = await indexClient.Documents.SearchAsync("*", searchParameters);
Console.WriteLine("Total documents in index (approx) = " + searchResults.Count.GetValueOrDefault());//Prints the total number of documents in the index
Please note that:
This count will be approximate.
Getting the count is an expensive operation so you should only do it with the very first request when implementing pagination.
For REST clients using the POST API, just include "count": "true" to the payload. You get the count in #odata.count.
Ref: https://learn.microsoft.com/en-us/rest/api/searchservice/search-documents

Select parts of a nlobjSearchResult

I have a large nlobjSearchResultSet object with over 18,000 "results".
Each result is a pricing record for a customer. There may be multiple records for a single customer.
As 18000+ records is costly in governance points to do mass changes, I'm migrating to a parent (customer) record and child records (items) so I can make changes to the item pricing as a sublist.
As part of this migration, is there a simple command to select only the nlapiSearchResult objects within the big object, which match certain criteria (ie. the customer id).
This would allow me to migrate the data with only the one search, then only subsequent create/saves of the new record format.
IN a related manner, is there a simple function call to return to number of records contained in a given netsuite record? For % progress context.
Thanks in advance.
you can actually get the number of rows by running the search with an added aggregate column. A generic way to do this for a saved search that doesn't have any aggregate columns is shown below:
var res = nlapiSearchRecord('salesorder', 'customsearch29', null,
[new nlobjSearchColumn('formulanumeric', null, 'sum').setFormula('1')]);
var rowCount = res[0].getValue('formulanumeric', null, 'sum');
console.log(rowCount);
To get the total number of records, the only way is do a saved search, an ideal way to do such search is using nlobjSearch
Below is a sample code for getting infinite search Results and number of records
var search = nlapiLoadSearch(null, SAVED_SEARCH_ID).runSearch();
var res = [],
currentRes;
var i = 0;
while(i % 1000 === 0){
currentRes = (search.getResults(i, i+1000) || []);
res = res.concat(currentRes );
i = i + currentRes.length;
}
res.length or i will give you the total number of records and res will give you all the results.

Resources