I'm trying to do a map/reduce that gets an item fi...
# suitescript
k
I'm trying to do a map/reduce that gets an item field from the most recent invoice in the last month for each customer and updates a field on the customer record to match. Can this be done with a single search, or do I need to do one search for customers and another for each of their most recent invoices?
s
Can't there be more than one item on each invoice? Does that matter in this instance?
k
It's a specific item
s
Oh okay so the item id would be part of your search criteria then?
k
it's only ever added once in each invoice
yeah it is
s
yeah you can definitely do this in map/reduce
k
yeah, just trying to find the right search criteria
s
getInput just have a transaction search
itemId is x
and
type is invoice
, put your customer and whatever date you want in the results
k
right but I need to do it once for each customer
s
in the map stage, read the customer id, and the date
use
context.write(customerId, date)
to group the results by customer
k
so that's two searches, one for customer, one for invoice item
s
no, single search on invoices
just reutrn the customer in the results
k
oh ok
because it'll only do each key once in reduce?
s
the map stage groups them together by key
k
I just don't want it to do two invoices for the same customer
s
so you would want your invoices grouped together by customer, then need to do something on the date logic in the reduce (i would just moment them, but you can prob just compare dates with native js Date objects)
So in your reduce, your context object would look like
Copy code
context = {
key: customerId,
values: [date1, date2, date3]
}
Use your preferred means for finding the most recent date in that array, and then write that data down to customer record with submitFields or record load/save. The field you are updating on the customer record is just a date field that needs that date?
k
but if getInputData is handing multiple invoices to map, how does it group them together?
if getInputData just returns the search result
s
getInput - will have a line for every invoice with that item on it, map - you tell it to group by customer by using
context.write
with customer id as the key
k
so multiple maps would write to the same reduce?
s
yes every entry into the map is grouping all the results by whatever key you desire
Copy code
define(['N/search'], function (search) {
    var exports = {};
    exports.getInputData = function getInputData() {
        return /* insert item search here */
    }

    exports.map = function map(context) {
        var results = JSON.parse(context.value);
        var customer = results.values.mainlinename.value; //something close to this
        var date = results.values.trandate; //or whatever date you want
        context.write(customer, date);
    }
    exports.reduce = function reduce(context) {
        var customer = context.key;
        var datesForThisCustomer = context.values;
        /* add some logic to find the most recent date */
        
    }
}
👍 1
Do you need this value stored on the customer record for searching later, or is this just info you want on the customer record when someone is viewing it?
k
it's storing the value for an integration to pick up later
I think this solution will work, thanks!
m
You can probably make this more performant by having the search return only the most recent invoice for each customer using a grouped search and when ordered by