node.js pg-promise и разбиение на страницы из API

Глядя на https://github.com/vitaly-t/pg-promise/wiki/Data-Imports есть очень подробный документ о том, как использовать его для импорта.

Однако, хотя это работает для демо-сценария, я не знаю, как применить это в моем случае.

Когда я делаю свой веб-звонок, я получаю фактические данные JSON и параметр в заголовке, который дает мне значение для следующей страницы (может быть дата, строка или числовое значение).

В примере сказано:

db.tx('massive-insert', t => {
    return t.sequence(index => {
        return getNextData(index)
            .then(data => {
                if (data) {
                    const insert = pgp.helpers.insert(data, cs);
                    return t.none(insert);
                }
            });
    });
})
    .then(data => {
        console.log('Total batches:', data.total, ', Duration:', data.duration);
    })
    .catch(error => {
        console.log(error);
    });

В этом случае sequence(index будет использовать индекс, который, кажется, увеличивает +1. Но в моем случае,

function getNextData(nextPage) {
    //get the data for nextPage
    .....
   //get the nextPage if exists for future use
   nextPage = response.next;

   resolve(data);
}

Мой вопрос в том, как я могу заменить index на nextPage в этом примере, так как каждое новое обещание должно использовать nextPage из предыдущего.

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: А если я хочу получить информацию из определенного значения nextPageInfo?

Например:

db.any('Select value from table')
      .then(function(value) {

var data = value; //not working

db.tx('massive-insert', t => {
    return t.sequence((index, data) => {
        return getNextData(index, data)
            .then(a => {
                if (a) {
                    const insert = pgp.helpers.insert(a.data, cs);
                    return t.none(insert).then(() => a.nextPageInfo);
                }
            })
    });
})
    .then(data => {
        // COMMIT has been executed
        console.log('Total batches:', data.total, ', Duration:', data.duration);
    })
    .catch(error => {
        // ROLLBACK has been executed
        console.log(error);
    })

}

person Alin    schedule 05.07.2017    source источник


Ответы (1)


После этого вопроса я расширил статью Импорт данных с новый раздел extras, который дает вам именно тот пример что вам нужно. Пример скопирован из статьи:

function getNextData(t, index, nextPageInfo) {
    // t = database transaction protocol

    // NOTE: nextPageInfo = undefined when index = 0

    return new Promise((resolve, reject) {

        /* pull the next data, according to nextPageInfo */            

        /* do reject(error) on an error, to ROLLBACK changes */
    
        if(/* there is still data left*/) {
            // if whateverNextDetails = undefined, the data will be inserted,
            // but the sequence will end there (as success).
            resolve({data, nextPageInfo: whateverNextDetails});
        } else {
            resolve(null);
        }   
    });
}

db.tx('massive-insert', t => {
    return t.sequence((index, data) => {
        return getNextData(t, index, data)
            .then(a => {
                if (a) {
                    const insert = pgp.helpers.insert(a.data, cs);
                    return t.none(insert).then(() => a.nextPageInfo);
                }
            })
    });
})
    .then(data => {
        // COMMIT has been executed
        console.log('Total batches:', data.total, ', Duration:', data.duration);
    })
    .catch(error => {
        // ROLLBACK has been executed
        console.log(error);
    });

Обратите внимание, что поскольку мы привязываем результат от getNextData к значению nextPageInfo, то, если его значение равно undefined, он сделает следующую вставку, но затем завершит последовательность (как успех).

person vitaly-t    schedule 05.07.2017
comment
Не могли бы вы объяснить мне, что на самом деле делают return t.none(insert).then(() => a.nextPageInfo);? Большое спасибо за ваш ценный ответ - person Alin; 05.07.2017
comment
Кроме того, если для каждого вставленного элемента мне нужно сделать еще одну выборку данных с дополнительной информацией, где лучше всего это сделать? - person Alin; 05.07.2017
comment
И последнее, я попытался установить nextPageInfo по умолчанию, потому что я хочу, например, вызывать API с определенной точки... Мне не удалось это сделать... Есть идеи? - person Alin; 05.07.2017
comment
Я отредактировал вопрос, чтобы вы могли видеть, что я пробовал. - person Alin; 06.07.2017
comment
Когда вы реализуете это так, как я показал, то внутри getNextData у вас будет this = протокол транзакции со всеми методами запроса, так что вы можете вызывать там любой запрос, который вам нравится. Я обновил пример, чтобы упомянуть об этом;) - person vitaly-t; 06.07.2017
comment
Я очень ценю, что вы нашли время, чтобы прояснить ситуацию. Как вы сказали, в getNextData я не понимаю, так как это не имеет для меня смысла, поскольку мне нужно иметь это значение ДО того, как я выполню начальный вызов db.tx, а не проверяю его каждый раз, когда вызывается getNextData. Итак, в основном мне нужно что-то вроде этого: это первый раз, когда я это вызываю? Если в таблице нет записи, начните с nextPageInfo=null и обработайте информацию. Если я запущу его снова позже, извлеките информацию о последней странице из таблицы ПЕРЕД запуском цикла, а затем используйте это значение, чтобы начать вызов db.tx из этого nextPageInfo. Имеет смысл? - person Alin; 06.07.2017
comment
Вот еще одна вещь, о которой я подумал: возможно, на основе nextPageInfo нужно запустить либо функции getNextData, либо, возможно, getPrevData, в зависимости от того, существует ли nextPageInfo или нет... - person Alin; 06.07.2017
comment
По вашей логике проще всего выполнить дополнительный запрос внутри getNextData всего один раз, когда он вызывается в первый раз, т.е. когда index = 0. И потом вы можете повторно использовать его результат на протяжении всей транзакции. А ваш nextPageInfo может содержать любую информацию, это может быть объект со всевозможными свойствами, включая исходный результат запроса. - person vitaly-t; 06.07.2017
comment
но нет способа передать это nextPageInfo в первую последовательность транзакций, непосредственно перед db.tx? Я безуспешно пытался это реализовать. - person Alin; 06.07.2017
comment
Это банально, на самом деле. Вы можете выполнить запрос до или внутри транзакции и использовать значение для последовательности. Проблемы, с которыми вы, похоже, сталкиваетесь на данный момент, больше связаны с использованием промисов, а не с библиотекой pg-promise, которая опирается на общую логику промисов. - person vitaly-t; 06.07.2017
comment
Что ж, буду пробовать, пока не разберусь. Спасибо за вашу помощь и за потрясающий pg-promise - person Alin; 06.07.2017
comment
@Alin Я обновил свой ответ относительно объекта транзакции, чтобы передать его явно, поскольку ранее он был неверным, извините за это. - person vitaly-t; 07.07.2017
comment
Спасибо за обновление. Я до сих пор не понимаю, как использовать этот t в getNextData и зачем мне его использовать, но я почитаю об этом подробнее. - person Alin; 07.07.2017