使用Q.Promises递归地从DynamoDB获取记录

时间:2017-05-17 07:49:41

标签: javascript node.js amazon-dynamodb q

我在使用递归dynamodb调用实现Q promises时遇到了麻烦,对nodejs和q是新手,考虑到dynamodb检索结果的限制,我们需要运行递归查询来获得所需的结果。

通常我们使用Q实现的查询,如

    function getDBResults(){

    var q = Q.defer();

    var params = {
        TableName: mytable,
        IndexName: 'mytable-index',

        KeyConditionExpression: 'id = :id',
        FilterExpression: 'deliveryTime between :startTime and :endTime',

        ExpressionAttributeValues: {
            ':startTime': {
                N: startTime.toString()
            },

            ":endTime": {
                N: endTime.toString()
            },
            ":id": {
                S: id.toString()
            }
        },
        Select: 'ALL_ATTRIBUTES',
        ScanIndexForward: false,
    };


     dynamodb.query(params, function(err, data) {
           if (err) {
               console.log('Dynamo fail ' + err);
               q.reject(err);
           } else {
               console.log('DATA'+ data);
               var results = data.Items;
               q.resolve(results);
           }
       });
      return q.promise;

}



getDBResults.then(
  function(data) {
    // handle data
  },
 function(err) {
        //handle error
  }
);

使用递归查询我可以得到结果,但我需要将这些结果用于另一个函数,但由于nodejs异步性质,下一个函数调用在递归查询函数完成其工作之前就已经发生了,现在我想要那个我从递归查询函数中获取所有结果,然后获取新函数的承诺,最后处理所有数据。

dynamodb的递归查询看起来像这样。

function getDBResults(){

    //var q = Q.defer();

     params = {
        TableName: mytable,
        IndexName: 'mytable-index',

        KeyConditionExpression: 'id = :id',
        FilterExpression: 'deliveryTime between :startTime and :endTime',

        ExpressionAttributeValues: {
            ':startTime': {
                N: startTime.toString()
            },

            ":endTime": {
                N: endTime.toString()
            },
            ":id": {
                S: id.toString()
            }
        },
        Select: 'ALL_ATTRIBUTES',
        ScanIndexForward: false,
    };



dynamodb.query(params, onQueryCallBack);


}


function onQueryCallBack(err, data) {
if (err) {
    console.log('Dynamo fail ' + err);
    console.error("Could not query db" + err);
} else {


if (typeof data.LastEvaluatedKey != "undefined") {
    console.log("query for more...");
    params.ExclusiveStartKey = data.LastEvaluatedKey;
    dynamodb.query(params, onQueryCallBack);
}
data.Items.forEach(function(item) {
    allResults.push(item);
});
//console.log('NO:OF Results:' + allResults.length);

//q.resolve(tickets);

//});

}

现在我希望我能最终得到结果,所以我可以在下一个函数中处理它们。

getDBResults.then(
  function(data) {
    // handle data
  },
 function(err) {
        //handle error
  }
);

请帮助我,对不起,如果它是一个愚蠢的问题,但是使用承诺的递归电话给我带来了障碍。

由于

2 个答案:

答案 0 :(得分:1)

首先,保留已有的保证功能。使用它作为递归解决方案的构建块,而不是试图改变它!

虽然可能需要两个小调整:

function getDBResults(startKey){
//                    ^^^^^^^^
    var q = Q.defer();
    var params = {
        ExclusiveStartKey: startKey,
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        … // rest as before
    };
    dynamodb.query(params, function(err, data) {
        if (err) {
           q.reject(err);
        } else {
           q.resolve(data);
//                   ^^^^ Not `data.Items`
        }
    });
    return q.promise;
}

现在我们可以使用它来轻松实现递归解决方案:

function getRecursiveDBResults(key) {
    return getDBResults(key).then(function(data) {
        if (typeof data.LastEvaluatedKey != "undefined") {
            return getRecursiveDBResults(data.LastEvaluatedKey).then(items) {
                return data.Items.concat(items);
            });
        } else {
            return data.Items
        }
    });
}

答案 1 :(得分:1)

以下是我如何解决问题,感谢Bergi也提供了解决方案

function getDBResults() {
    var q = Q.defer();
    var dynamodb = core.getDynamoDB();



    params = {
        TableName: mytable,
        IndexName: 'mytable-index',

        KeyConditionExpression: 'id = :id',
        FilterExpression: 'deliveryTime between :startTime and :endTime',

        ExpressionAttributeValues: {
            ':startTime': {
                N: startTime.toString()
            },

            ":endTime": {
                N: endTime.toString()
            },
            ":id": {
                S: id.toString()
            }
        },
        Select: 'ALL_ATTRIBUTES',
        ScanIndexForward: false,
    };


    var results = [];
    var callback = function(err, data) {
        if (err) {
            console.log('Dynamo fail ' + err);
            q.reject(err);
        } else if (data.LastEvaluatedKey) {
            params.ExclusiveStartKey = data.LastEvaluatedKey;
            dynamodb.query(params, callback);
        } else {
            q.resolve(results);
        }
        data.Items.forEach(function(item) {
            results.push(item);
        });

    }


    dynamodb.query(params, callback);

    return q.promise;
}