Автоматическое увеличение значения в Firebase

Как автоматически увеличить значение, хранящееся в Firebase, из клиента Android?

На данный момент: я объявляю int id = 1. Когда я увеличиваю, я вижу, что значения 2, 3 и т. д. сохраняются. Это нормально, но когда я перезапускаю проект, id снова устанавливается равным 1.

Я хочу, чтобы она вела себя как статическая переменная, поэтому я могу создать идентификатор, который будет изменяться от 1 до бесконечности без сброса.

ОБНОВЛЕНО ОШИБКА

Я использовал следующее, чтобы передать ссылку Firebase и строку в функцию incrementCounter.

if(language_chosen.equalsIgnoreCase("english"))
 {
   Firebase publRef = f.child("Language").child("English").child("Message");
   Firebase newPublRef = publRef.push();
   writeMsgActivity demo = new writeMsgActivity();
   demo.incrementCounter(newPublRef,the_msg_enter);                                 
  }

Теперь я пытаюсь использовать переданную ссылку и строку в public void incrementCounter(Firebase publref,String my_msg) в методе oncomplete, но это дает мне ошибку.

   public void incrementCounter(Firebase publref,String my_msg) {
    publref.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(final MutableData currentData) {
            if (currentData.getValue() == null) {
                currentData.setValue(1);
            } else {
                currentData.setValue((Long) currentData.getValue() + 1);
            }

            return Transaction.success(currentData);
        }

        public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
            if (firebaseError != null) {
                System.out.println("Firebase counter increment failed.");
            } else {
                System.out.println("Firebase counter increment succeeded.");

                Map<String, Object> publ = new HashMap<String, Object>();
                publ.put("pubMsg", my_msg);
                publ.put("id",currentData);
                publref.setValue(publ);
            }
        }
    });
}

ОБНОВЛЕНО РЕШЕНО

                final Firebase upvoteref = new Firebase("https://shareurday.firebaseio.com/Message/"+msg_id+"/upvotes"); 

            upvoteref.runTransaction(new Transaction.Handler() {
                @Override
                public Transaction.Result doTransaction(final MutableData currentData) {
                    if (currentData.getValue() == null) {
                        currentData.setValue(1);
                    } else {
                        currentData.setValue((Long) currentData.getValue() + 1);
                    }
                    return Transaction.success(currentData);
                }

                public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
                    if (firebaseError != null) {
                        System.out.println("Firebase counter increment failed.");
                    } else {
                        System.out.println("Firebase counter increment succeeded.");
                    }
                }
            });

Переменная msg_id — это случайно сгенерированный идентификатор из push.


person nothingness    schedule 07.03.2015    source источник
comment
Я не уверен, какой код вы используете с Firebase и что здесь означает Reload? Но если вы вызовете ту же функцию (которая устанавливает id=1) при перезагрузке, вы получите id 1. Вы должны установить id в каком-то файле/базе данных и продолжать обновлять в этом хранилище.   -  person aberry    schedule 07.03.2015
comment
Я могу установить его в базе данных, но каждый раз, когда я повторно запускаю программу, она сбрасывается до целого числа id = 1.   -  person nothingness    schedule 07.03.2015
comment
При каждом запуске вам нужно проверять наличие в файле/db... INSERT IF NOT EXISTS ELSE UPDATE . Ваш вопрос кажется общим, но да, вам нужно отслеживать все одновременные изменения, если объект/запись являются общими.   -  person aberry    schedule 07.03.2015


Ответы (2)


Вот пример метода, который увеличивает один счетчик. Основная идея заключается в том, что вы либо создаете запись (устанавливая ее равной 1), либо мутируете существующую запись. Использование здесь транзакции гарантирует, что если несколько клиентов одновременно попытаются увеличить значение счетчика, все запросы в конечном итоге будут успешными. Из документации Firebase (выделено мной):

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

public void incrementCounter() {
    firebase.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(final MutableData currentData) {
            if (currentData.getValue() == null) {
                currentData.setValue(1);
            } else {
                currentData.setValue((Long) currentData.getValue() + 1);
            }

            return Transaction.success(currentData);
        }

        @Override
        public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
            if (firebaseError != null) {
                Log.d("Firebase counter increment failed.");
            } else {
                Log.d("Firebase counter increment succeeded.");
            }
        }
    });
}
person stkent    schedule 07.03.2015
comment
Можете ли вы показать мне, как передавать переменные, я не умею с этим. - person nothingness; 07.03.2015
comment
Чего именно вы пытаетесь достичь? Если вы сохраняете данные с помощью push, они автоматически генерируются с уникальным идентификатором и не требуют ручного увеличения счетчика. См., например. firebase.com/docs/android/guide/saving- data.html#section-push . Дайте мне знать, если это будет лучшим решением для вас. - person stkent; 07.03.2015
comment
Мне нужно создать идентификатор для каждого сообщения, чтобы я мог сравнивать ответы с другим деревом. (Я сделал эту часть), например. каждое сообщение имеет идентификатор, и каждый ответ на это сообщение будет использовать идентификатор этого сообщения. Поэтому, когда я получаю ответы, они будут в идентификаторе сообщения. - person nothingness; 07.03.2015
comment
Тогда кажется, что использование push, а затем вызов getKey по результату, как описано в ссылке, которую я разместил выше, вероятно, является правильным решением для вас? Если это так, я обновлю свой ответ, чтобы отразить это. - person stkent; 07.03.2015
comment
ваш ответ идеален, мне просто нужно знать, как использовать переданную ссылку и строку. потому что я хочу, чтобы идентификатор сообщения был похож на 1,2,3, а не на jshfjkhhsbfjds из push. - person nothingness; 07.03.2015
comment
Я должен уйти сейчас, если вы можете обновить, я был бы очень признателен, спасибо за ваше время. - person nothingness; 07.03.2015
comment
Ok. В последней строке кода, который вы добавили к вопросу, у вас есть publref.setValue(publ);. Это должно быть newPublRef.setValue(publ);? - person stkent; 07.03.2015
comment
да, я передал ссылку здесь: incrementCounter(Firebase publref,String my_msg) - person nothingness; 07.03.2015
comment
Возможно, вы хотите заменить пару строк publ.put("pubMsg", my_msg); publ.put("id",currentData); одной строкой publ.put(currentData, my_msg);, но это трудно сказать, потому что вы не указываете, каким образом ваше текущее решение работает неправильно... - person stkent; 07.03.2015
comment
Он работает с publ.put("pubMsg", my_msg); publ.put("id",currentData);, кроме my_msg. Потому что это было пройдено - person nothingness; 07.03.2015
comment
Что такое the_msg_enter? Это пустая строка? Я не вижу, чтобы его где-то присваивали. - person stkent; 07.03.2015
comment
Ну, здесь это пустая строка, но в моем коде она из текстового редактора. - person nothingness; 07.03.2015
comment
Так что же не работает? Это не работает.. недостаточно, чтобы продолжать. - person stkent; 07.03.2015
comment
Что не работает, так это прохождение incrementCounter(Firebase publref,String my_msg) здесь - person nothingness; 07.03.2015
comment
Что здесь не работает ЗНАЧИТ? Я опускаю вопрос до тех пор, пока вы не сможете отредактировать его, чтобы дать четкие указания. Как стоит вопрос, это никому не нужно. - person stkent; 07.03.2015
comment
Что не работает, так это передача incrementCounter(Firebase publref,String my_msg) после передачи. Я хочу использовать переданную переменную, но publ.put(pubMsg, my_msg); и publref.setValue(publ); они не работают во внутренних методах oncompleted. - person nothingness; 07.03.2015
comment
Попробуйте public void incrementCounter(final Firebase publref, final String my_msg) {. Ваше предупреждение IDE, вероятно, указывало, что это подходящее исправление. - person stkent; 07.03.2015
comment
Он не сохранялся в объекте, а сохранялся, например, в ссылке. final Firebase f = new Firebase("https://shareurday.firebaseio.com/msg"); так сохраняется msg:1 это не то, что мне нужно. Я хочу, чтобы он сохранялся в объекте карты, например, msg --> id:1, и это привело к сбою моей программы после запуска. - person nothingness; 08.03.2015
comment
Вы пробовали publ.put(currentData, my_msg);, как я указал ранее? - person stkent; 08.03.2015
comment
извините за столько хлопот, у меня все работает, я загружу решение. Оно смотрело мне в лицо. Спасибо большое за вашу помощь!!! - person nothingness; 10.03.2015
comment
Я работаю над той же проблемой в узле, и мне было любопытно, выходит ли getValue() в приведенном выше примере в базу данных. Если это так, я предполагаю, что runTransaction будет блокировать все вызовы до тех пор, пока транзакция не будет зафиксирована. Разве в firebase нет функции увеличения на стороне сервера, такой как DynamoDB? Конечно, вы всегда можете возразить, чтобы не изменять состояние объекта и просто добавить его в другой список. - person Brett Mathe; 11.11.2016

В firestore добавлена ​​новая функция для автоинкрементных значений. Так просто как

document("fitness_teams/Team_1").
  updateData(["step_counter" : FieldValue.increment(500)])

ссылка: https://firebase.googleblog.com/2019/03/increment-server-side-cloud-firestore.html

Используемый ниже код в моем проекте.

var firestore = Firestore.instance;
firestore.collection('student').document('attendance').updateData({'total_attendace': FieldValue.increment(1)});
person AtulK    schedule 19.02.2020