Изменение пути к элементу в Firebase

#javascript #firebase #firebase-realtime-database

#javascript #firebase #firebase-база данных в реальном времени

Вопрос:

Я хотел бы изменить местоположение элемента в базе данных. Я попытался сначала удалить элемент из одного местоположения, затем переместить его в другое. Вот метод:

 firebase.database().ref('completed').on('value', (snapshot) => {
  snapshot.forEach((snapchild) => {
    if(snapchild.val().title === item.title amp;amp; snapchild.val().id === item.id) {
      firebase.database().ref('todos').push(snapchild.val()).then(() => {
        firebase.database().ref(`anotherlocation/${snapchild.key}`).remove()
      }
    }
  })
})
  

К сожалению, это не работает, элемент удаляется, но он не добавляется в другое место.
Правильный ли это способ сделать это?

Редактировать: добавлена структура firebase.db

Комментарии:

1. Можете ли вы добавить данные вашей базы данных и объяснить, где вы пытаетесь изменить путь?? Из вашего вопроса я вижу, что вы также хотите удалить его из одного места.

2. У меня просто есть список todo элементов и список completed элементов, я хочу удалить элемент из completed и вернуть его обратно в todo .

3. Да, вставьте эти дочерние элементы todo и completed items в виде кода, чтобы мы могли понять структуру вашей базы данных и помочь вам с этим.

4. Когда я пытаюсь запустить созданный мной метод, оба completed и todos удаляются.

Ответ №1:

Есть несколько проблем с кодом:

  1. Вы вызываете push в новом расположении, что означает, что элемент добавлен с новым ключом. Вероятно, вы захотите, чтобы в новом местоположении элемент имел тот же ключ, что и в старом местоположении.
  2. Вы выполняете две операции с базой данных, что означает, что первая может быть успешной, в то время как другая завершается неудачей. Используя одно обновление с несколькими местоположениями, вы можете гарантировать, что либо обе записи завершатся успешно, либо ни одна из них не произойдет.
  3. Вы читаете больше элементов, чем необходимо. Поскольку вы знаете id элементы, которые хотите переместить, вы можете ограничить операцию чтения этим.

В коде:

 var query = firebase.database().ref('completed').orderByChild('id').equalTo(item.id);
query.on('value', (snapshot) => {
  snapshot.forEach((snapchild) => {
    if(snapchild.val().title === item.title) {
      var updates = {};
      updates['/todos/' snapchild.key] = snapchild.val();
      updates['/completed/' snapchild.key] = null;
      firebase.database().ref().update(updates);
    }
  })
})
  

Это перемещает завершенный элемент с item.id обратно в todos . Я не уверен, что это именно тот ход, который вы хотите выполнить, поскольку это не было ясно из вашего вопроса. Если нет, вам придется обновить пути в updates .

Комментарии:

1. Предоставленный код, безусловно, является правильным способом решения моего вопроса, однако, когда я его запускаю, он completed становится null , как и предполагалось, todo обновляется и немедленно также удаляется.

2. Это, скорее всего, потому, что у вас нет разрешения на запись в completed . Проверьте свои правила безопасности.

3. Вы имеете в виду это: "rules": { ".read": true, ".write": true } ?

Ответ №2:

Однажды я написал метод, который сначала создает копию, а затем удаляет исходный узел. это всего лишь нужно было бы перенести с Java на JavaScript , что должно быть довольно простой задачей. доказано, что порядок операций, по крайней мере, рабочий. как правило, вы должны заменить .on('value') на .once('value') , потому что дальнейших событий не будет — и удаление должно быть перехвачено ChildEventListener на родительском узле (или как бы это ни вызывалось в JavaScript ). если вы хотите написать этот реальный сценарий должным образом, инкапсуляция в транзакцию имела бы смысл для данного сценария.

 /** relocates a record from one to another path (v2). */
protected void move(final DatabaseReference source, final DatabaseReference target) {
    source.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            target.setValue(snapshot.getValue(), new DatabaseReference.CompletionListener() {

                @Override
                public void onComplete(DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {

                    /* if not the operation has failed */
                    if (databaseError != null) {
                        if(mDebug) {Log.w(LOG_TAG, databaseError.getMessage());}
                    } else {

                        /* remove the source path */
                        source.removeValue(new DatabaseReference.CompletionListener(){
                            @Override
                            public void onComplete(DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
                                if(mDebug) {Log.d(LOG_TAG, "moved "   source.toString()   " to "   target.toString());}
                            }
                        });
                    }
                }
            });
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            if(mDebug) {Log.w(LOG_TAG, databaseError.getMessage());}
        }
    });
}