Search code examples
mapreducenetsuitesuitescript2.0

SuiteScript - Map/Reduce - no context value is passed to the summarize stage from reduce stage


I am new to this and currently learning SuiteScript. I'm having trouble understanding why there is no context value being passed from the reduce function to the summarize function. The log results show nothing for the context value except for: {"type":"mapreduce.Summary","dateCreated":"2023-08-29T17:02:27.014Z","seconds":9,"usage":190,"concurrency":5,"yields":0}", which is causing an error to occur. However, the Reduce Context log shows the values as expected.

Would anyone be kind enough to help me understand what I'm doing wrong or what I should be doing instead? Thank you in advance for your assistance; I truly appreciate it.

Regards

My code sample below and I am expecting to get the 'fileList' context from the reduce stage to summarize stage.

code sample below:

function reduce(context) {
    try {

        var transactions = JSON.parse(context.values[0]); // Parse the file contents loaded from getInputData

        log.debug('Reduce Context', transactions); // This logs the values as expected

        if (transactions && transactions.length > 0) {
            // Iterate through file transactions array
            transactions.forEach(function (transaction) {
                /** .... performing other tasks with transaction object
                .........to create and save journal
                */
                // Build the file list array and write context that needs to be moved
                context.write({
                    key: "fileList",
                    value: {
                        fieldId: transaction.fileId,
                        duplicate: transaction.duplicate,
                        failed: transaction.failed
                    }
                });
            });
        }
    } catch (e) {
        log.error('Reduce Error', 'Error in Reduce function => ' + e.name + ' : ' + e.message);
    }
}

function summarize(context) {
    try {

        log.debug('Summarized Context', context); // The log results show nothing for the context value

        fileList = JSON.parse(context.values[0]); // Parse the context values loaded from reduce stage
        if (fileList && fileList.length > 0) {
            //Iterate through the file list array and move each file to the relevant folder
            fileList.forEach(function (file) {
                var fileObj = file.load({
                    id: file.fileID
                });
                if (file.duplicate === "Y") {
                    fileObj.folder = DUPLICATE_FILE_FOLDER_ID; // Move the file from Pending Folder to Duplicate Folder
                } else if (file.failed === "Y") {
                    fileObj.folder = FAILED_FILE_FOLDER_ID; // Move the file from Pending Folder to Failed Folder
                } else {
                    fileObj.folder = PROCESSED_FILE_FOLDER_ID; // Move the file from Pending folder to Processed Folder
                }

                fileObj.save();
            });
        }
    } catch (err) {
        log.audit('File Moving Error', err.name + ' : ' + err.message);
    }
}

Solution

  • summarize uses a different context. There is no values member.

    For what you presented you'd want something like:

    const fileRefs = [];
    ctx.output.iterator().each((key, value)=>{
       if(key == 'fileList'){
          var fileRef = JSON.parse(value);
          fileRefs.push(fileRef);
          return true;
       }
    });
    fileRefs.
       filter(uniques(ref=>ref.fileId)). // create a function uniques that only returns true for the first instance of fileId NOTE your code also used fieldId where it looks like it should use fileId
       forEach(ref=>{ 
          ... your original logic
       });