Android - 从 Cloud Firestore 中检索存储在文档中的自定义对象

3

我正在如下使用Cloud Firestore:

enter image description here

集合“events”保存使用唯一事件ID作为名称的文档。在这些文档中有许多“EventComment”对象,每个对象代表用户发表的评论。
要将“EventComment”对象添加到文档中,我使用以下代码:
EventComment mcomment = new EventComment();
mcomment.setComment("this is a comment");
Map<String, EventComment> eventMap = new HashMap<>();
eventMap.put(Long.toHexString(Double.doubleToLongBits(Math.random())), mcomment);

    firestore.collection("events").document(event_id)
            .set(eventMap, SetOptions.merge()).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            Toast.makeText(EventCommentsActivity.this, "ya bastud", Toast.LENGTH_SHORT).show();
        }
});

我创建了一个由字符串和我的对象“EventComment”组成的HashMap,并将其设置在文档中。
然而,当我想检索给定文档中包含的所有“EventComment”对象时,我无法将其转换为EventComment对象,即我不能这样做:
    DocumentReference docRef = db.collection("events").document("vvG17ZfcLFVna8");
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        EventComment comment = documentSnapshot.toObject(EventComment.class);
    }
});

此外,尝试将documentSnapshot转换为HashMap会出现“unchecked cast”消息,并最终失败。思路是使用注释来填充RecyclerView。
我在考虑是否需要重新构建数据存储方式?
非常感谢您的任何建议。
干杯
1个回答

5
你猜得没错,你需要重新构建数据存储方式。我之所以这么说是因为你在实际数据库中存储EventComment对象的方式是不正确的。正如你可以在有关配额和限制的官方文档中看到的那样,一个文档的最大大小为1MiB。因此,如果你继续像这样存储数据,很快就会达到1MiB的限制。
请记住,Cloud Firestore 优化了存储大量小型文档的集合。为了解决这个问题,我建议你更改数据库结构,像这样:
Firestore-root
   |
   --- events (collection)
   |     |
   |     --- eventId (document)
   |     |     |
   |     |     --- //event details
   |     |
   |     --- eventId (document)
   |           |
   |           --- //event details
   |
   --- comments (collection)
         |
         --- eventId (document)
               |
               --- eventComments (collection)
                     |
                     --- eventCommentId (document)
                     |      |
                     |      --- //event comment details
                     |
                     --- eventCommentId (document)
                            |
                            --- //event comment details

从下面的代码可以看到,每个类型为EventComment的对象都会作为单独的文档添加到events集合中。如果想要读取所有事件对象,请使用以下代码:

DocumentReference docRef = db.collection("events");
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        EventComment comment = documentSnapshot.toObject(EventComment.class);
    }
});

编辑:

如果您想要针对特定eventId列出comments的列表,请再次查看上述数据库结构,以了解如何表示它。正如您所看到的,我已经添加了一个名为comments的新集合,其中每个给定eventId中的新评论也作为单独的文档存储。我设计这种结构是为了避免嵌套的映射。

如果您有兴趣,可以看一下我的其中一个教程,我在其中逐步解释了如何构建应用程序所需的数据库结构。


嗨,Alex,感谢您的回复。这确实更有意义,但是如果我想要给定eventID的“评论”列表,最好如何表示?我的模型在代码中需要定义一个列表,还是可以有一个子集合的评论?EventComment模型旨在表示一个用户发表的1条评论。 - ZachOverflow
1
不用谢,@Zach。为了达到你想要的效果,请查看我的更新答案。 - Alex Mamo
1
嗨,Alex,我看了你的教程,非常有用 - 谢谢!它确实起作用了,我能够在代码中获取集合并将其映射到ArrayList。现在我正在观看你的Firebase RecyclerView教程 :) - ZachOverflow
1
通过您的教程和 Stackoverflow 的问答,我已经成功地将它填充到 RecyclerView 中了 :) - ZachOverflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接