我能想到的最有效的模式如下:
Firestore-root
|
--- questions (collections)
| |
| --- questionId (document)
| |
| --- questionId: "02cubnmO1wqyz6yKg571"
| |
| --- title: "Question Title"
| |
| --- date: August 27, 2018 at 6:16:58 PM UTC+3
| |
| --- comments (colletion)
| | |
| | --- commentId
| | |
| | ---commentId: "5aoCfqt2w8N8jtQ53R8f"
| | |
| | ---comment: "My Comment"
| | |
| | ---date: August 27, 2018 at 6:18:28 PM UTC+3
| |
| --- likes (colletion)
| | |
| | --- likeId (document)
| | |
| | --- userId: true
| |
| --- views (colletion)
| | |
| | --- viewId (document)
| | |
| | --- userId: true
| |
| --- tags ["tagId", "tagId"]
|
--- tags (collections)
|
--- tagId (document)
|
--- tagId: "yR8iLzdBdylFkSzg1k4K"
|
--- tagName: "Tag Name"
其中comments、likes 和views 是questionId 文档下的集合。与在 Firebase 实时数据库中显示问题列表的位置不同,您将下载整个问题对象,在 Cloud Firestore 中,这不再是问题。因此,为了避免使用where 方法进行查询,您可以简单地得到一个这样的特定问题:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
DocumentReference questionIdRef = rootRef.collection("questions").document(questionId);
questionIdRef.get().addOnCompleteListener(/* ... */);
因为一个问题可以有数百、数千甚至更多的 cmets、喜欢和视图,将数据存储到数组中对您没有帮助。根据official documentation:
Cloud Firestore 针对存储大量小文档进行了优化。
例如,要获取特定问题的所有 cmets,可以使用以下查询:
Query query = rootRef.collection("questions/"+questionId+"comments").orderBy("date", Query.Direction.DESCENDING);
因为一个问题只能有几个标签,你可以简单地使用一个数组。要获取带有特定标签的所有问题,您可以使用以下查询:
Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", tagId);
还有一点要记住,即使tags 对象作为数组存储在数据库中,document.get("tags") 也会返回 ArrayList 而不是 array。
如果您还想计算收藏中的点赞数或任何其他文档数,请参阅我在此 post 中的回答。
编辑:
根据您的 cmets:
如果我想向用户展示最喜欢的问题。我怎么能这样做?
您应该在问题对象中添加喜欢的数量作为属性,然后您可以根据它查询数据库,如下所示:
Query query = rootRef.collection("questions").orderBy("numberOfLikes", Query.Direction.DESCENDING);
根据this,您还可以将点赞数存储在 Firebase 实时数据库中,您可以使用 Firebase Transactions 增加/减少它。
其次,如果我想显示与数学等标签相关的所有问题(显示所有具有数学标签的问题)??
如上所述,您可以利用whereArrayContains 方法。您还可以将标签存储为字符串而不是 id。为此,您需要更改此结构:
--- tags ["tagId", "tagId"]
到
--- tags ["mathematics", "chemistry"]
代码应该是这样的:
Query query = rootRef.collection("questions/"+questionId+"tags").whereArrayContains("tags", "mathematics");
语句(userId: true) 节省了大量的数据重复
是的。