Entry Points – MR Scripts
getInputData
The getInputData function is called when the map/reduce script is triggered. getInputData can return many different types of data.
Three common structures are:
A simple array
An array of objects
An object
I will use Input to refer to the data returned by getInputData and Output to refer to the data passed to the map stage (each element being another call to the reduce stage).
If you return an array, NetSuite will consider the index of the array to be the key and the value to be the value.
Input: ['Work Order 1', 'Work Order 2', 'Work Order 3', 'Work Order 4']
Output: {0: 'Work Order 1', 1: 'Work Order 2', 2: 'Work Order 3', 3: 'Work Order 4'}
If I return an array of objects, NetSuite will consider the value of the id property to be the index and the value to be a JSON string of the object.
Input: [ { id: 'Work Order 1', name: 'Work Order 1' }, { id: 'Work Order 2', name: 'Work Order 2' }]
Output: { '0': '{"id":"Work Order 1","name":"Work Order 1"}', '1': '{"id":"Work Order 2","name":"Work Order 2"}' }
If I return an object, NetSuite simply uses the keys and values of the object.
Input: { 'Work Order 1': '123', 'Work Order 2': '324' }
Output { 'Work Order 1': '123', 'Work Order 2': '324' }
You can also do more exotic things like return a query object or a file object. I have found that it is much more practical to either load the file or run the query in the getInputData function and return the results manually.
map
The context object passed to the map function contains the following properties we care about:
mapContext.key – The key of the key/value pair
mapContext.value – The value of the key/value pair
We process the data however we see fit and return an object with the key/value pair we want to use in the reduce stage. In this function we are only returning one key/value pair, as such it should simply be an object with a single property.
reduce
Now we finally get to the stage where we process our data. The context object passed to the reduce function contains a few properties:
reduceContext.key – The key of the key/value pair
reduceContext.values – An array of values for all of the key/value pairs with the same key returned by the map function
reduceContext.write – A function that can be used to write data to be used in the summarize function
An example of using the reduceContext.write function:
const reduce = (reduceContext) => {
const customerid = reduceContext.key
const workOrderIds = reduceContext.values
const total = getTotal(customerid, workOrderIds)
reduceContext.write({
customerid,
total,
})
}
summarize
The summarize function is called after all of the reduce functions have been called.
The context object passed to the summarize function contains many properties related to the script execution such as script usage, concurrency, etc.
In addition the summaryContext object contains three objects related to the other stages:
summaryContext.inputSummary – An object containing information about the data returned by the getInputData function
summaryContext.mapSummary – An object containing information about the data returned by the map function
summaryContext.reduceSummary – An object containing information about the data returned by the reduce function
To get the data we saved in the reduce function, we use the summaryContext.output.iterator() function.
const summarize = (summaryContext) => {
summaryContext.output.iterator().each((key, value) => {
const { customerid, total } = JSON.parse(value)
log.debug('customerid', customerid)
log.debug('total', total)
return true
})
}
Map/reduce scripts take a while to get the hang of. Although for smaller tasks you may be able to get away with a scheduled script, inevitably you will run into a situation where you are running out of script usage units or it is taking too long to run. In these situations, map/reduce scripts are a great solution.