从Cloud Firestore检索复杂文档

时间:2018-08-18 17:05:42

标签: java android firebase google-cloud-firestore

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

数据存储如下:

database structure

书籍文档包含作者和翻译者子集合。为了检索书籍的完整列表,有一个对数据库的调用,如下所示(我省略了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,则似乎回调与检索到的Books一样多。因此,有没有一种方法可以优化此代码,使得每本书只有一个回叫,而每个作者和翻译者文档只有一个回叫?

谢谢!

1 个答案:

答案 0 :(得分: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以及相应的公开获取者。要说,假设是book对象的翻译器,您可以使用以下代码行:

Translator translator = book.getTranslator();

以与作者相同的方式。

Author autothor = book.getAuthor();