В двух словах: когда дан последний объект для определенного заказа, startAfter()
должен возвращать пустые результаты (я думаю), но это не так. Почему нет?)
У меня большая коллекция, которая нуждается в периодическом обслуживании. Я хотел бы сделать это, читая пакеты, делая пакетные записи, затем продолжая рекурсивно.
Я думаю, что я построил правильную структуру следующим образом (в конечном итоге это будет облачный код. Я запускаю его в браузере, чтобы избежать болезненного цикла build-deploy-test с использованием облака)
function cleanupFoos(startAfter) {
let query = db.collection('myCollection').orderBy('createdAt').limit(200)
if (startAfter) query.startAfter(startAfter)
return query.get().then(querySnapshot => {
startAfter = _.last(querySnapshot.docs)
let batch = db.batch()
let promises = querySnapshot.docs.map(doc => cleanupFoo(doc, batch))
return Promise.all(promises).then(() => batch)
}).then(batch => {
return batch.commit()
}).then(() => {
return startAfter ? cleanupFoos(startAfter) : null
})
}
function cleanupFoo(doc, batch) {
// return a promise
}
// call it
cleanupFoos()
Но этот код зацикливается бесконечно. Наблюдая в отладчике одной коллекции документов (myCollection: [ { just this one doc } ]
), я получаю этот единственный документ при первом вызове. Это также последний документ, так что
startAfter = _.last(querySnapshot.docs) // --> { just this one doc }
При рекурсивном вызове я вижу, что startAfter настроен на то, что я ожидаю: первый (и последний) документ. Я ожидаю, что get()
теперь должен возвращать пустой querySnapshot. Но он возвращает один и тот же документ, вызывая еще один раунд, потом еще один ... Это неправильно, верно?