Получение сложных документов из Cloud Firestore

Я пытаюсь получить набор сложных объектов из Cloud Firestore.

Данные хранятся следующим образом:

Получение сложных документов из 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);
                    }
                }
            });
}

Однако, если я помещаю журналы, кажется, что количество обратных вызовов равно количеству извлеченных книг. Следовательно, есть ли способ оптимизировать этот код таким образом, чтобы был только один обратный вызов для каждой книги и один для каждого документа автора и переводчика?

Заранее спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 еще два поля: author и translator и соответствующие общедоступные геттеры. Чтобы получить, скажем, переводчик из объекта книги, вы можете использовать следующую строку кода:

Translator translator = book.getTranslator();

Таким же образом можно поступить и с автором.

Author autothor = book.getAuthor();

Большое спасибо за ответ. Это уменьшило мой код на 200%. Мой класс книги выглядит следующим образом: общедоступный класс Книга {частный строковый идентификатор; частное строковое имя; частные авторы ArrayList <Author>; частные переводчики ArrayList <Translator>; } Геттеры и сеттеры уже есть. С помощью упомянутого вами метода я смог получить все атрибуты, кроме вложенных коллекций авторов и переводчиков. Мне нужно сделать еще один вызов базы данных, чтобы получить их все?

Charitha De Silva 19.08.2018 12:27

Рад это слышать. Нет необходимости делать еще один звонок. Вы можете получить их прямо из книжного объекта.

Alex Mamo 19.08.2018 12:35

Еще раз спасибо. Теперь в Книжном классе есть: частный автор-автор; частные авторы ArrayList <Author>; частный переводчик-переводчик; частные переводчики ArrayList <Translator>; а также их соответствующие геттеры и сеттеры. Однако я не могу получить из него данные об авторе и переводчике. Например, если вы возьмете вложенную коллекцию «Авторы», в ней есть такие документы, как «author0», «author1» и т. д. Будет ли это гарантировать, что все эти авторы будут извлечены за один раз? Я все еще немного запутался.

Charitha De Silva 19.08.2018 12:47

Пока объект книги содержит автора и переводчика, вы можете получить его за одну операцию.

Alex Mamo 19.08.2018 13:21

да. Я думаю, поскольку у класса книги есть вложенные коллекции, нам нужно выполнить еще один обратный вызов, чтобы собрать всех авторов и переводчиков. Большое спасибо за помощь.

Charitha De Silva 19.08.2018 15:03

@CharithaDeSilva В итоге с каким решением вы пошли? Я все еще пытаюсь понять это. Большое спасибо!

Rafael 03.10.2020 19:03

@AlexMamo Это то, что обнаруживает Firebase? Как это работает?

Rafael 03.10.2020 19:04

@Rafael Я выбрал решение, предоставленное Алексом, и оно сработало нормально!

Charitha De Silva 04.10.2020 06:51

Другие вопросы по теме