我正在创建一个某种个人词汇的应用程序。数据库具有以下形式。
现在我需要实现分页,部分检索用户的单词,但保留字典顺序。将单词保持为键(/user/{uid}/words/{word}
)是不合适的,因为将来不可能处理同形异义词(因为它们的键会重合)。我决定为每个用户保留其他属性word
,以便我可以致电db.getReference().child("users").child(uid).child("words").orderByChild("word")
。
这将检索用户的所有单词。现在我需要对此查询进行分页,例如首先下载20个单词,然后再下载20个单词,但保留字典顺序。
{
"users" : {
"yXYSqB016JMr1FIc85pvMbvqDDt2" : {
"words" : {
"5v1a1PaDKnTvvOH19kaFTa1iyOx2" : {
"index" : 1,
"word" : "apple"
},
"kXHakBKxk9TrAlWL1vTOCe0akk80" : {
"index" : 2,
"word" : "house"
},
"xSKSqB312JMrsFig15pvMbvqAAt0" : { ... }
}
},
"zCAtMpl9uxSjG9dJarGktTTs20w2" : { ... }
},
"vocabulary" : {
"en" : {
"5v1a1PaDKnTvvOH19kaFTa1iyOx2" : {
"definitions" : {
"a fruit that grows on a tree" : true
},
"word" : "apple"
},
"kXHakBKxk9TrAlWL1vTOCe0akk80" : { ... },
"xSKSqB312JMrsFig15pvMbvqAAt0" : { ... }
}
}
}
答案 0 :(得分:2)
您似乎来自SQL思维方式,通过指定要获取的项目数和要跳过的项目数进行分页。这是基于索引的分页。
另一方面,Firebase使用基于光标的分页。你告诉它要获得的物品和开始(或结束)的项目。您可以通过您订购的属性的值来标识此项目,在您的情况下,这是word
的值。由于相同的值可能会出现在多个子节点中,因此您还可以指定要作为第二个参数开始/结束的子节点的键(以5v1a1...
开头的内容)。
所以说你的页面大小为2。你得到前两个单词:
DatabaseReference allWords = db.getReference().child("users").child(uid).child("words");
Query firstPage = allWords.orderByChild("word").limitToFirst(2);
当您将听众附加到此时,您将获得前两个单词。您需要记住第一页中word
和最后一个字的关键字:
String lastWordOnPreviousPage = "house";
String lastKeyOnPreviousPage = "5v1a1...";
现在,如果您需要两个单词的第二页,请通过以下方式获取:
Query secondPage = allWords.orderByChild("word").startAt(lastWordOnPreviousPage, lastKeyOnPreviousPage).limitToFirst(2);