SuiteScript Map/Reduce:Reduce到Summarize阶段无Context值传递求助
SuiteScript Map/Reduce 问题:Summarize阶段无法获取Reduce传递的数据
问题描述
我是SuiteScript新手,学习时遇到一个问题:Reduce函数里的日志能正常显示预期值,但Summarize函数无法获取Reduce阶段传递的context值,日志只显示{"type":"mapreduce.Summary","dateCreated":"2023-08-29T17:02:27.014Z","seconds":9,"usage":190,"concurrency":5,"yields":0},导致报错。我需要把Reduce阶段的fileList数据传递到Summarize阶段处理。
原始代码
function reduce(context) { try { var transactions = JSON.parse(context.values[0]); // 解析getInputData加载的文件内容 log.debug('Reduce Context', transactions); // 这里日志能正常输出预期值 if (transactions && transactions.length > 0) { // 遍历交易数组 transactions.forEach(function (transaction) { /** .... 处理transaction对象的其他逻辑 ......... 创建并保存日记账 */ // 构建文件列表并写入需要传递的上下文 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); // 日志仅显示Summary对象,没有预期的数据 fileList = JSON.parse(context.values[0]); // 尝试解析Reduce阶段传递的值 if (fileList && fileList.length > 0) { // 遍历文件列表,将文件移动到对应文件夹 fileList.forEach(function (file) { var fileObj = file.load({ id: file.fileID }); if (file.duplicate === "Y") { fileObj.folder = DUPLICATE_FILE_FOLDER_ID; // 从待处理文件夹移到重复文件夹 } else if (file.failed === "Y") { fileObj.folder = FAILED_FILE_FOLDER_ID; // 从待处理文件夹移到失败文件夹 } else { fileObj.folder = PROCESSED_FILE_FOLDER_ID; // 从待处理文件夹移到已处理文件夹 } fileObj.save(); }); } } catch (err) { log.audit('File Moving Error', err.name + ' : ' + err.message); } }
问题分析
- Summarize阶段数据获取方式错误:Summarize的
context是Summary对象,无法直接通过context.values[0]获取Reduce输出的数据,必须通过context.output.iterator迭代器遍历Reduce阶段的输出结果。 - Reduce阶段写入数据类型错误:SuiteScript Map/Reduce中,
context.write的value必须是字符串类型,直接传入对象会导致序列化异常,无法正确传递到Summarize阶段。 - 变量未声明:Summarize中的
fileList未用var/let/const声明,属于全局变量,可能引发意外问题。 - 字段名拼写不一致:代码中存在
fileId和fileID的拼写差异,会导致无法正确获取文件ID。
解决方案
修正后的Reduce函数
function reduce(context) { try { var transactions = JSON.parse(context.values[0]); log.debug('Reduce Context', transactions); if (transactions && transactions.length > 0) { transactions.forEach(function (transaction) { /** .... 其他处理逻辑 */ // 将对象转为JSON字符串后写入,确保数据能正确传递 context.write({ key: "fileList", value: JSON.stringify({ fileId: transaction.fileId, // 统一字段名,避免拼写错误 duplicate: transaction.duplicate, failed: transaction.failed }) }); }); } } catch (e) { log.error('Reduce Error', 'Error in Reduce function => ' + e.name + ' : ' + e.message); } }
修正后的Summarize函数
function summarize(context) { try { var fileList = []; var iterator = context.output.iterator(); var result; // 遍历所有Reduce输出的键值对,收集数据到数组 while ((result = iterator.next()) != null) { fileList.push(JSON.parse(result.value)); } log.debug('Collected File List', fileList); if (fileList.length > 0) { fileList.forEach(function (file) { var fileObj = file.load({ id: file.fileId // 使用统一的字段名 }); if (file.duplicate === "Y") { fileObj.folder = DUPLICATE_FILE_FOLDER_ID; } else if (file.failed === "Y") { fileObj.folder = FAILED_FILE_FOLDER_ID; } else { fileObj.folder = PROCESSED_FILE_FOLDER_ID; } fileObj.save(); }); } } catch (err) { log.audit('File Moving Error', err.name + ' : ' + err.message); } }
关键修改点
- Reduce阶段:用
JSON.stringify()将对象转为字符串后写入,确保数据序列化正确;统一字段名为fileId,避免拼写错误。 - Summarize阶段:通过
context.output.iterator()遍历所有Reduce输出结果,收集到局部变量fileList中;修正字段名引用,确保能正确获取文件ID。
内容的提问来源于stack exchange,提问作者Curious Explorer
相关产品推荐
相关产品推荐

