Добавление элемента в список в базе данных Firebase

у меня есть следующая структура базы данных военнослужащих. uIds тип List<String>. Я пытаюсь добавить еще один uId под uIds с увеличенным индексом. setValue() и updateChildren() потребуется, чтобы я извлек существующие данные, и push() добавит элемент со случайно сгенерированной строкой в качестве ключа вместо увеличенного индекса. Есть ли более простой способ, который не требует извлечения существующих данных? Спасибо!

  "requests" : {
    "request001" : {
      "interests" : [ "x" ],
      "live" : true,
      "uIds" : [ "user1" ]  // <---- from this
    },
    "request002" : {
      "interests" : [ "y" ],
      "live" : true,
      "uIds" : [ "user2" ]
    }
  }

--------------------------------

Edit:

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

  "requests" : {
    "-KSVYZwUQPfyosiyRVdr" : {
      "interests" : [ "x" ],
      "live" : true,
      "uIds" : [ "user1", "user2" ]   // <--- to this
    },
    "-KSl1L60g0tW5voyv0VU" : {
      "interests" : [ "y" ],
      "live" : true,
      "uIds" : [ "user2" ]
    }
  }

предложение ишмаэльмакитлы,mDatabase.child("requests").child("request001").setValue(newRequest), перезапишет " request001 "с"newRequest". Поэтому я должен получить существующие данные " request001 "и добавить" user2 " в список uIds. Это будет что-то вроде это:

mDatabase.child("requests").child("request001").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Request newRequest = dataSnapshot.getValue(Request.class);
        newRequest.uIds.add("user2");
        mDatabase.child("requests").child("request001").setValue(newRequest);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}

});

но мне интересно, нужен ли этот процесс, так как я пытаюсь просто добавить один элемент в список uIds.

4 ответов


на Firebase документация по созданию данных, которые масштабируются предлагает использовать другую структуру данных:

"requests" : {
  "-KSVYZwUQPfyosiyRVdr" : {
    "interests" : { "x": true },
    "live" : true,
    "uIds" : { 
      "user1": true, 
      "user2": true 
    }
  },
  "-KSl1L60g0tW5voyv0VU" : {
    "interests" : { "y": true },
    "live" : true,
    "uIds" : { 
      "user2": true 
    }
  }
}

вот несколько причин, почему эта структура данных работает лучше:

  • каждый uid теперь может автоматически отображаться только один раз. Мы по существу смоделировали наши данные как set, вместо использования массива.
  • добавление элемента теперь так же просто, как ref.child("uUids").child("user3").setValue(true)
  • теперь вы можете проверить, если uid существует в ваших правилах безопасности.

Я начал повторять про себя: всякий раз, когда вы обнаружите, что делаете array.contains("xyz"), вы, вероятно, должны использовать набор вместо массива. приведенное выше сопоставление с "key": true является реализацией набора на Firebase.

эффективность

некоторые люди могут думать, что массивы являются более эффективным способом хранения данных, но в случае Firebase это не так:

что вы см.:

"uIds" : [ "user1", "user2" ]

какие магазины Firebase:

"uIds" : {
  "0": "user1",
  "1": "user2"
}

так хранить набор почти такой же:

"uIds" : { 
  "user1": true, 
  "user2": true 
}

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

private DatabaseReference mDatabase;
// get reference to your Firebase Database.
mDatabase = FirebaseDatabase.getInstance().getReference();
//and here you add a new child to your 'requests' collection
//I am assuming you have a Request model like this..
Request newRequest = new Request(some-params);
mDatabase.child("requests").child(someRequestId).setValue(newRequest);

вы можете взглянуть на основных инструкция по эксплуатации сохранение данных на Android Firebase.

обновление: После вашего комментария-я думаю, что то, что вы хотите сделать, может быть достигнуто следующим образом: Вы используете push() метод, который генерирует уникальный идентификатор каждый раз, когда новый ребенок добавляется указанная ссылка Firebase:

Firebase newRequestRef = mDatabase.child("request").push();
newRequestRef.setValue(newRequest);

это должно помочь.

надеюсь, это поможет.


добавление 2 центов Франк ван Puffelen ответ, вы можете использовать ключ от принудительной отправки в качестве уникального идентификатора запроса. Кроме того, если вы используете хэш-карту для обновления ребенка, ваша БД не будет переопределена

 // Create a node on Server and get key
  String requestID = AdminController.getInstance().referenceFromUrl
                        .child(END_POINT_REQUESTS)
                        .push().getKey();

  //use key as ID for your Object which you want to push as unique identifier of your model
  requestToPush.setRequestId(requestID );

 //Add updated Model Object in a Map to update DB instead of over writing
 requestsMap.put(requestID , requestToPush);

 //Update newly created DB nodes with data
   referenceFromUrl
            .child(END_POINT_REQUESTS)
            .updateChildren(productsMap,
                    new DatabaseReference.CompletionListener() {
                        @Override
                        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

                            if (databaseError != null) {
                                Log.e(TAG, "Error: Data could not be saved "
                                        + databaseError.getMessage());
                            } else {
                                Log.e(TAG, "Success : Data saved successfully.");
                            }
                        }
                    });

результат

enter image description here


есть старая добрая статья из официального блога Firebase, объясняющая, почему мы должны избегать массива в нашей базе данных:массивы-зло

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

"requests" : {
    "<pushKey1>" : {
        "interests" : [ "x" ],
        "live" : true,
        "uIds" : {
            "<pushKey1>" : "user1",
            "<pushKey2>" : "user2"
        }
    },
    "<pushKey2>" : {
        "interests" : [ "y" ],
        "live" : true,
        "uIds" : {
            "<pushKey1>" : "user2"
        }
    }
}

для получения pushKey, вы можете использовать push () метод (то же самое, что вы сделали с каждым Request номенклатура)

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

String requestKey = "request001";
mDatabase.child("requests").child(requestKey).child("uIds").push().setValue("user2");

комментарий здесь, Если у вас есть вопросы, надеюсь, что это помогает :)