java - 结构化 Firestore Android 以获取多个 where 检查
问题描述
我想基于多个数组项读取集合。
db.collection("questionCollection")
.orderBy("questionID", Query.Direction.DESCENDING)
.whereArrayContains("tags","EveryDayScience")
//.whereArrayContains("tags","generalKnowledge")//this cannot be possible
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
if (queryDocumentSnapshots.isEmpty()) {
Log.d(TAG, "onSuccess: LIST EMPTY");
return;
} else {
// Convert the whole Query Snapshot to a list
// of objects directly! No need to fetch each
// document.
questionList = queryDocumentSnapshots.toObjects(QuestionBO.class);
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
e.printStackTrace();
Toast.makeText(mContext,"Failed",Toast.LENGTH_LONG).show();
}
});
我需要阅读所有属于everyDayScience
和generalKnowledge
/或多个标签的问题,如物理、化学等。
我的应用架构如下所示。我如何构建我的数据库以读取多个标签上的集合?
编辑 我需要有问题的分页,比如,最喜欢的和评论问题。你给我推荐了这个结构
在 MongoDb 中是这样实现的
解决方案
如果您尝试链接多个whereArrayContains()
方法,您很可能会收到以下错误:
原因:java.lang.IllegalArgumentException:无效查询。查询仅支持具有单个数组包含过滤器。
所以不幸的是,Firestore 只能允许一次调用whereArrayContains()
方法。在这种情况下,您应该考虑扩充您的数据库结构以允许反向查找,方法是在您的每个标签对象(文档)下添加tagCollection
一个名为的新集合tagQuestion
,您应该在其中添加所有标有特定标签的问题。您的数据库结构应如下所示:
Firestore-root
|
--- tagCollection (collection)
|
--- EveryDayScience (document)
| |
| --- tagQuestions (collection)
| |
| --- tagQuestionId
| |
| --- //question details
|
--- generalKnowledge (document)
|
--- tagQuestions (collection)
|
--- tagQuestionId
|
--- //question details
要从两个特定标签中获取所有问题,请使用以下代码行:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query firstQuery = rootRef.collection("tagCollection").document("EveryDayScience").collection("tagQuestions");
Query secondQuery = rootRef.collection("tagCollection").document("generalKnowledge").collection("tagQuestions");
Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();
Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
@Override
public void onSuccess(List<Object> list) {
//Do what you need to do with the list of questions from within two tags
}
});
但你会想,为什么要这样做?为什么要复制数据?好吧,就 Firebase 而言,复制数据没有问题。这是一种非常常见的做法,denormalization
为此,我建议您观看此视频,Firebase 数据库的非规范化是正常的。这适用于实时数据库,但同样的原则适用于 Cloud Firestore。
复制数据时,需要牢记一件事。与添加数据的方式相同,您需要对其进行维护。换句话说,如果你想更新/删除一个项目,你需要在它存在的每个地方都这样做。
推荐阅读
- r - 使用 R 中的正则表达式对数据进行分叉
- react-native - 将 Native json 反应为平面列表视图数据
- sql - 为什么 SQL 引擎在使用 LIMIT 时扫描索引列上的整个表?
- android - 如何理解 Kotlin 中有趣的 buildString(builderAction: (StringBuilder) -> Unit) : String?
- mysql - 存储过程的输出参数未显示
- javascript - 用户注册和认证(注册和登录)Nodejs
- r - knitr,抑制来自纯素 metaMDS 的 nms 压力
- python - 布尔设置的“if”条件:== 1、== True 或只是省略?
- java - 仅使用 Log4J 避免日志伪造
- c - 无法从 C 中的 .dat 文件中读取