Gar*_*aye 31 database data-modeling firebase swift google-cloud-firestore
对于我的应用程序来说,能够从firebase中的集合中随机选择多个文档至关重要.
由于Firebase(我知道)没有内置本机函数来实现这样做的查询,我首先想到的是使用查询游标来选择随机的开始和结束索引,前提是我有多少文档集合.
这种方法只能以有限的方式起作用,因为每个文件都会按照其相邻文件的顺序提供; 但是,如果我能够通过其父集合中的索引选择文档,我可以实现随机文档查询,但问题是我找不到任何描述如何执行此操作的文档,即使您可以执行此操作.
这是我想要做的,考虑以下firestore架构:
root/
posts/
docA
docB
docC
docD
Run Code Online (Sandbox Code Playgroud)
然后在我的客户端(我在Swift环境中)我想编写一个可以执行此操作的查询:
db.collection("posts")[0, 1, 3] // would return: docA, docB, docD
Run Code Online (Sandbox Code Playgroud)
无论如何我能做到这一点吗?或者,有不同的方式我可以以类似的方式选择随机文档吗?
请帮忙.
Dan*_*ath 63
编写文档时,首先生成一个随机的64位整数,并将其添加为一个名为的字段__name__.
这将创建一个索引,随机排序您的文档.
现在,要选择随机文档,请生成另一个随机64位整数.我们将在查询中使用它来选择索引中的随机位置并读取下一个文档:
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
Run Code Online (Sandbox Code Playgroud)
检查这是否已返回文档.如果没有,请反转方向并再试一次:
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: lowValue)
.order(by: "random")
.limit(to: 1)
Run Code Online (Sandbox Code Playgroud)
如果您使用我们的客户端库中提供的随机生成的自动ID,您可以使用相同的系统随机选择文档.
在此系统中,生成要在查询中使用的新自动ID.现在选择集合中大于新自动ID的文档(限制1).
与不可知版本略有不同的是,您目前无法按降序排序文档ID.这意味着如果您的查询未返回文档,则需要生成新的自动ID并重试.
通常,您希望一次选择多个随机文档.根据您想要的权衡取舍,有两种不同的方法来调整上述技术.
这种方法很简单.只需重复该过程,包括每次选择一个新的随机整数.
此方法将为您提供随机的文档序列,而无需担心重复查看相同的模式.
权衡是它将比下一个方法慢,因为它需要为每个文档单独往返服务.
在这种方法中,只需将限制数量增加到所需文档即可.这有点复杂,因为您可能会__name__在通话中返回文档.然后,您需要以相同的方式获取丢失的文档,但限制仅限于差异.如果您知道总共有多个文档而不是您要求的数字,那么您可以忽略永远无法获得足够文档的边缘情况.
与该解决方案的权衡是重复的顺序.虽然文档是随机排序的,但如果您最终重叠范围,您将看到之前看到的相同模式.尽管如此,有两种方法可以缓解这种担忧.首先,插入的文档将最终编织在中间,逐渐改变序列.其次,您可以通过random在每次更新时使用新数字更新字段来加速这一过程.
这种方法比"冲洗和重复"更快,因为您将在一次通话中请求所有文档.
ajz*_*zbc 11
发布此信息可帮助以后遇到此问题的任何人。
如果您使用的是自动ID,则可以生成新的自动ID并查询最接近的自动ID,如Dan McGrath的Answer中所述。
我最近创建了一个随机报价API,需要从Firestore集合中获取随机报价。
这就是我解决该问题的方法:
var db = admin.firestore();
var quotes = db.collection("quotes");
var key = quotes.doc().id;
quotes.where(admin.firestore.FieldPath.documentId(), '>=', key).limit(1).get()
.then(snapshot => {
if(snapshot.size > 0) {
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
}
else {
var quote = quotes.where(admin.firestore.FieldPath.documentId(), '<', key).limit(1).get()
.then(snapshot => {
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
})
.catch(err => {
console.log('Error getting documents', err);
});
}
})
.catch(err => {
console.log('Error getting documents', err);
});
Run Code Online (Sandbox Code Playgroud)
查询的关键是这样的:
.where(admin.firestore.FieldPath.documentId(), '>', key)
Run Code Online (Sandbox Code Playgroud)
如果找不到文档,则以相反的操作再次调用它。
我希望这有帮助!
如果有兴趣,您可以在GitHub上找到我的API的这一特定部分
| 归档时间: |
|
| 查看次数: |
11293 次 |
| 最近记录: |