【问题标题】:Retrieving Complex Documents from Cloud Firestore从 Cloud Firestore 检索复杂文档
【发布时间】:2019-01-25 09:51:56
【问题描述】:

我正在尝试从 Cloud Firestore 中检索一组复杂的对象。

数据存储如下:

图书文档包含作者和翻译者子集。为了检索完整的书籍列表,需要对数据库进行如下调用(我省略了 Book 对象的所有其他属性,并保留了理解问题所必需的内容):

public void getBooks(final BookRetrievable bookRetrievable) {
    FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
    ArrayList<Book> books = new ArrayList<>();

    firebaseFirestore.collection("books")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (DocumentSnapshot documentSnapshot : task.getResult()) {
                            Book book = new Book();
                            book.setId(documentSnapshot.getString("id"));
                            book.setName(documentSnapshot.getString("name"));
                            book.setStatus(Status.valueOf(documentSnapshot.getString("status")));
                            documentSnapshot.getReference().collection("authors")
                                    .get()
                                    .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                                        @Override
                                        public void onComplete(@NonNull Task<QuerySnapshot> task) {
                                            if (task.isSuccessful()) {
                                                ArrayList<Author> authors = new ArrayList<>();
                                                for (DocumentSnapshot documentSnapshot : task.getResult()) {
                                                    Author author = new Author();
                                                    author.setId(documentSnapshot.getString("id"));
                                                    author.setNameInEnglish(documentSnapshot.getString("nameInEnglish"));
                                                    author.setNameInSinhalese(documentSnapshot.getString("nameInSinhalese"));
                                                    author.setWebsite(documentSnapshot.getString("website"));
                                                    authors.add(author);
                                                }

                                                book.setAuthors(authors);

                                                documentSnapshot.getReference().collection("translators")
                                                        .get()
                                                        .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                                                            @Override
                                                            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                                                                if (task.isSuccessful()) {
                                                                    ArrayList<Translator> translators = new ArrayList<>();
                                                                    for (DocumentSnapshot documentSnapshot : task.getResult()) {
                                                                        Translator translator = new Translator();
                                                                        translator.setId(documentSnapshot.getString("id"));
                                                                        translator.setNameInEnglish(documentSnapshot.getString("nameInEnglish"));
                                                                        translator.setNameInSinhalese(documentSnapshot.getString("nameInSinhalese"));
                                                                        translator.setWebsite(documentSnapshot.getString("website"));
                                                                        translators.add(translator);
                                                                    }

                                                                    book.setTranslators(translators);

                                                                    books.add(book);

                                                                    books.sort((Book b1, Book b2) -> b1.getSeriesNo().compareTo(b2.getSeriesNo()));
                                                                    bookRetrievable.onCallback(books);
                                                                } else {
                                                                    bookRetrievable.onCallback(null);
                                                                }
                                                            }
                                                        });
                                            } else {
                                                bookRetrievable.onCallback(null);
                                            }
                                        }
                                    });
                        }
                    } else {
                        bookRetrievable.onCallback(null);
                    }
                }
            });
}

但是,如果我放 Logs,似乎有与检索到的书籍数量一样多的回调。因此,有没有办法优化这段代码,使得每本书只有一个回调,每个作者和翻译文档只有一个回调?

提前致谢!

【问题讨论】:

    标签: java android firebase google-cloud-firestore


    【解决方案1】:

    是的,有。为了获取所有书籍对象,不需要创建Book类的对象,你可以像这样从DocumentSnapshot对象中获取:

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    CollectionReference booksRef = rootRef.collection("books");
    booksRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                for (DocumentSnapshot document : task.getResult()) {
                    Book book = document.toObject(Book.class);
                    //Do whay you need to do with your Book object
                }
            }
        }
    });
    

    如果您需要获取特定书籍的作者和翻译者,请在您的 Book 类中添加另外两个文件,authortranslator 以及相应的公共 getter。要从 book 对象中获取翻译器,您可以使用以下代码行:

    Translator translator = book.getTranslator();
    

    你可以对作者做同样的事情。

    Author autothor = book.getAuthor();
    

    【讨论】:

    • 非常感谢您的回答。它使我的代码减少了 200%。我的书类如下: public class Book { private String id;私有字符串名称;私有 ArrayList 作者;私有 ArrayList 翻译器; } getter 和 setter 已经在那里了。从您提到的方法中,我能够获取除 Authors 和 Translators 子集合之外的所有属性。我需要再次调用数据库来检索所有这些吗?
    • 很高兴听到这个消息。不,没有必要再打一个电话。您可以直接从 book 对象中获取它们。
    • 再次感谢。现在书类有以下内容:私人作者作者;私有 ArrayList 作者;私人翻译翻译;私有 ArrayList 翻译器;以及它们各自的 getter 和 setter。但是,我无法从中检索我的作者和译者数据。例如,如果您采用子集合“作者”,它具有“作者0”、“作者1”等文档。这是否能确保一次性检索所有这些作者?我还是有点迷茫。
    • 只要 book 对象包含作者和翻译者,您就可以在一次操作中检索。
    • 是的。我认为由于 Book Class 有子集合,我们需要进行另一个回调来收集所有作者和翻译者。非常感谢所有的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 2018-08-18
    • 2011-04-11
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多