Suitescript 2.0 ResultSet。每个回调函数超过4000

时间:2019-01-15 17:01:21

标签: javascript callback netsuite suitescript suitescript2.0

几年前,我写了一个脚本(下面没有写过代码,因为-所以相当数量或生锈; D),结果集现在超过了4000条记录,这在编写脚本时是没有想到的。错误如下:

  

{“类型”:“ error.SuiteScriptError”,“名称”:“ SSS_SEARCH_FOR_EACH_LIMIT_EXCEEDED”,“消息”:“ nlobjSearchResultSet.forEachResult(callback)一次最多不能返回4000个搜索结果。请修改您的搜索条件或修改回调逻辑,以使返回的结果不超过4000。” ...

解决此问题的最佳方法是使用其他技术(例如Map / Reduce-我现在必须学习),或者有一种方法可以过滤搜索,因此仅从中返回一定数量的结果搜索和其余记录在后续执行中得到返回/处理?

谢谢

//...
invoiceSearch.run().each(function(result) {
    // ensure script usage okay
    if (usageOkay()) {
        entityID = result.getValue({
            'name': 'internalid',
            'join': 'customer',
            'summary': search.Summary.GROUP
        });

        var maxAmountCustomerRecord = result.getValue({
            'name': 'custentity_amount_maxorder_2years',
            'join': 'customer',
            'summary': search.Summary.GROUP
        });

        var maxAmountCalculated = result.getValue({
            'name': 'formulacurrency',
            'formula': 'CASE WHEN {closedate} >= ADD_MONTHS(SYSDATE, -(12 * 2)) THEN {amount} ELSE NULL END',
            'summary': search.Summary.MAX
        });
        // in case the calculated amount is null then make it 0
        maxAmountCalculated = maxAmountCalculated || 0.0;
        // Only write to the customer record when a change is required
        if (maxAmountCustomerRecord != maxAmountCalculated) {
            updateRecord(entityID, maxAmountCalculated);
            log.debug('Updating customer with entityID: ' + entityID + ', to maxAmount: ' +
                maxAmountCalculated + ', from previous value of ' + maxAmountCustomerRecord);
        }
        return true;
    }
    else {
        // If remaining script usage low, reschedule script
        rescheduleScript(entityID);
    }
});
//....

3 个答案:

答案 0 :(得分:2)

我的建议,或者对于SuiteScript 2.0中批量处理的最佳实践,也许是最佳做法,是使用Map / Reduce而不是计划脚本。他们当然有一些学习上的弯路,但是它们非常强大。

快速提示将是:

  1. 您的getInputData入口点仅可以创建/加载现有脚本中的invoiceSearch,然后将其返回
  2. 您无需使用M / R就可以摆脱所有使用情况监视
  3. 您的reduce入口点实际上就是您在那里的if语句的胆量。

希望它应该是一个相当简单的转换。

答案 1 :(得分:2)

尽管Eric的答案是我可能会去做的事情,但有时还是要执行计划脚本。当然,在这种情况下,如果您认为自己可以在一天内完成预定运行中的所有项目,那么一个简单的解决方法是:

var count = 0;
invoiceSearch.run().each(function(result) {
   count++;
   if(count == 4000) return false;
   if(usageOk(){
     ...
     return true;
   }else{
     rescheduleScript(entityID);
      return false; // end the each and you may never hit 4k anyway
   }
});

答案 2 :(得分:2)

我个人想生成完整的搜索,然后从那里解析它:

我将此功能与任何搜索对象一起使用,以1000个块的形式编译结果:

function getAllResults(s) {
    var results = s.run();
    var searchResults = [];
    var searchid = 0;
    do {
        var resultslice = results.getRange({start:searchid,end:searchid+1000});
        resultslice.forEach(function(slice) {
            searchResults.push(slice);
            searchid++;
            }
        );
    } while (resultslice.length >=1000);
    return searchResults;
}   

然后,当我要处理任何搜索时,例如:

var mySearch = search.create({
                type:'invoice',
                columns: [
                    {name: 'tranid'},
                    {name: 'trandate'},
                    {name: 'entity', sort: (params.consolidated)?search.Sort.ASC:undefined },
                    {name: 'parent',join:'customer', sort: (!params.consolidated)?search.Sort.ASC:undefined},
                    {name: 'terms'},
                    {name: 'currency'},
                    {name: 'amount'},
                    {name: 'amountremaining'},
                    {name: 'fxamount'},
                    {name: 'fxamountremaining'},
                ],
                filters: [
                    {name: 'mainline', operator:'is',values:['T']},
                    {name: 'trandate', operator:'onorbefore', values: [params.startDate] }
                ]
            });

var myResults = getAllResults(mySearch );

myResults.forEach(function(result) {

//... do stuff with each result

});

在超过20,000条记录的数据集上,我用它取得了很好的结果。