无法在Firebase实时数据库中实现分页



下面是我用来为从firebase实时数据库检索的数据实现分页的代码。基本上,我试图根据页码获得前n个内容,然后从第一个查询中检索到的数据中获得最后n个内容。

function getUserSnapshotOrVerifyUserId(username, idToken, cb) {
if (username == null || username.length == 0 || idToken == null || idToken.length == 0)
return cb({
status: "error",
errorMessage: "Missing params."
}, null);

admin.auth().verifyIdToken(idToken).then(decodedToken => {
let uid = decodedToken.uid;
admin.database().ref().child("users").orderByChild("username").equalTo(username).once('value', snapshot => {
if (!snapshot.exists())
return cb({
status: "error",
message: "invalid-profile"
});
snapshot.forEach(child => {
const id = child.val().id;
if (id !== uid)
return cb({
status: "error",
message: "Invalid ID"
});
admin.database().ref("users/" + id).once("value", snapshot => {
if (!snapshot.exists())
return cb({
status: "error",
errorMessage: "user not found."
});

return cb(null, id, snapshot);
});
});
});
}).catch(err => cb({
status: "error",
message: err
}));
}
exports.getUserContentTestPagination = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const username = req.body.username || req.query.username;
const idToken = req.body.idToken;
const limit = 2;
const page = req.body.page || 1;
const limitToFirst = page * limit;
const limitToLast = limit;

getUserSnapshotOrVerifyUserId(username, idToken, async (err, id) => {
if(err) return res.json(err);
const uploadsRef = admin.database().ref('uploads').orderByChild('createdBy').equalTo(id)
const firstnquery = uploadsRef.limitToFirst(limitToFirst);
const lastnquery = firstnquery.limitToLast(limitToLast);
lastnquery.once("value", snapshot => {
res.json({
snapshot
})
})

})
} catch (err) {
res.json({
status: "error",
message: err
})
}
});
});

这将返回一个函数超时,但是,当我尝试使用firstnquery获取前n个数据时,它将按预期返回前n个数据。问题是lastnquery。如有任何帮助,不胜感激。

更新1:

exports.getUserContentTestPagination = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const username = req.body.username || req.query.username;
const idToken = req.body.idToken;
const limit = 2;
const page = req.body.page || 1;

let lastKnownKeyValue = null;
getUserSnapshotOrVerifyUserId(username, idToken, async (err, id) => {
if(err) return res.json(err);
const uploadsRef = admin.database().ref('uploads');
const pageQuery = uploadsRef.orderByChild('createdBy').equalTo(id).limitToFirst(limit);

pageQuery.once('value', snapshot => {
snapshot.forEach(childSnapshot => {
lastKnownKeyValue = childSnapshot.key;
});
if(page === 1){
res.json({
childSnapshot
})
} else {
const nextQuery = uploadsRef.orderByChild('createdBy').equalTo(id).startAt(lastKnownKeyValue).limitToFirst(limit);
nextQuery.once("value", nextSnapshot => {
nextSnapshot.forEach(nextChildSnapshot => {
res.json({
nextChildSnapshot
})
})
})
}
});
})
} catch (err) {
res.json({
status: "error",
message: err
})
}
});
});

在查询中同时使用limitToFirstlimitToLast是非常罕见的。事实上,我很惊讶这没有引发错误:

const firstnquery = uploadsRef.limitToFirst(limitToFirst);
const lastnquery = firstnquery.limitToLast(limitToLast);

Firebase查询基于游标。这意味着要获取下一页的数据,您必须知道上一页上的最后一项。这与大多数基于偏移量的数据库不同。Firebase不支持基于偏移量的查询,所以你需要知道createdBy的值和上一页最后一项的键。

有了这个,你可以得到下一页的项目:

admin.database().ref('uploads')
.orderByChild('createdBy')
.startAt(idOfLastItemOfPreviousPage, keyOfLastItemOfPreviousPage)
.limitToFist(pageSize + 1)

我强烈建议查看一下关于在实时数据库上实现分页的其他一些问题,因为那里也有一些很好的示例和解释。

最新更新