Обновление нескольких документов с использованием транзакции Firestore - PullRequest
0 голосов
/ 16 апреля 2020

Вариант использования: У меня есть несколько заметок, каждая из которых привязана к ярлыку. Если пользователь удаляет метку, все заметки, связанные с этой меткой, привязываются к метке по умолчанию. Поэтому, чтобы это сработало, мне сначала нужно выяснить все заметки с этой меткой, заменить идентификатор метки идентификатором метки по умолчанию и, наконец, удалить выбранную метку. Все это должно быть Atom c и, следовательно, Firestore Transaction.

Проблема возникает потому, что я хочу get() несколько документов, запустив query. Поскольку это операция async, вся цель транзакции исчезает. Примеры, которые я видел в документации, относятся к одному документу.

FirebaseConstants.getRootRef()  // db reference
        .runTransaction((Transaction.Function<Void>) transaction -> {
            FirebaseConstants.getNotesRef()  // Notes collection reference
                    .whereEqualTo("labelDetails.id", "<old_label_id>")
                    .get()
                    .addOnSuccessListener(snapshots -> {
                        ArrayList<String> listIds = new ArrayList<>();

                        for (DocumentSnapshot snap : snapshots.getDocuments()) {
                            listIds.add(snap.getId());
                        }

                        for (String id : listIds) {
                            FirebaseConstants.getNotesRef()
                                    .document(id)
                                    .update("labelDetails.id", "<default_label_id>");
                        }

                        // Labels collection reference
                        FirebaseConstants.getLabelsRef().document("<old_label_id>").delete();
                    });
            return null;
        })
        .addOnSuccessListener(snapshots -> {
            Toast.makeText(this, "transaction success", Toast.LENGTH_SHORT).show();
        })
        .addOnFailureListener(e -> {
            Toast.makeText(this, "transaction failed", Toast.LENGTH_SHORT).show();
        });

Итак, мне бы очень хотелось узнать, как справиться с этим делом. Я знаю, что могу get() сначала сопоставить идентификаторы, а затем выполнить транзакцию внутри get OnSuccessListener (или даже выполнить пакетную запись, поскольку get() уже выполнена), но это не гарантирует согласованности данных. между get() и моим update(), не так ли?

Следовательно, мне интересно, как это должно быть сделано. Как get и update несколько документов, используя Transaction?

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Firestore поддерживает , а не , поддерживает согласованность транзакций в клиентских приложениях, которые получают документы посредством запросов. Обратите внимание, что у объекта transaction нет способа выполнить запрос. Вы можете выполнять только отдельные операции get () для документов.

Чтобы получить обновление atomi c, необходимо использовать предоставленный объект Транзакция для всех операций поиска и обновления документов. Сначала вы должны прочитать документ, прежде чем сможете его написать (но если вы читаете документ, вам не нужно его писать).

Если вам нужно работать с документами, которые получены в результате запроса Вы должны выполнить запрос за пределами транзакции и запомнить идентификаторы каждого документа для использования в транзакции. Если результаты запроса изменятся до завершения транзакции (например, будет добавлен или удален документ), то ваша транзакция будет иметь дело с данными, которые «устарели».

A Транзакция имеет смысл только в том случае, если вам нужно прочитать содержимое документа, чтобы принять решение, прежде чем его написать. В вашем случае вы фактически не используете содержимое каждого документа, чтобы решить, что с ним делать. В этом случае достаточно пакетной записи.

1 голос
/ 16 апреля 2020

Я могу сначала получить () соответствующие идентификаторы, а затем выполнить транзакцию внутри OnSuccessListener get (или даже пакетной записи, поскольку get () уже выполнена), но это не гарантирует согласованность данных между get ( ) и мое обновление (), не так ли?

Да, пакетная запись решит вашу проблему. В этом случае нет проблемы согласованности, потому что пакетная запись - это операции atomi c, либо все операции выполнены успешно, либо ни одна из них не применяется. Таким образом, вы должны создать нужный запрос, получить все необходимые документы и добавить их в пакет операций обновления. В конце просто позвоните commit(). Имейте в виду, что существует ограничение в 500 операций на партию. Если вам нужно больше, вы должны создать свой собственный механизм для обновления документов по 500 операций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...