В нашей структуре базы данных каждый «Пользователь» содержит несколько идентификаторов ставок, каждый идентификатор ставки представляет собой точку входа в базу данных «Задания».
В настоящее время, когда мы хотим перебрать все задания одного человека, код выглядит примерно так:
final DatabaseReference mDatabaseJobs = FirebaseDatabase.getInstance().getReference().child("Jobs");
DatabaseReference mDatabaseUser = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUser.getUid());
mDatabaseUser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot userBids = dataSnapshot.child("listOfBids");
final int num_user_bids = (int) userBids.getChildrenCount();
for(final DataSnapshot job : userBids.getChildren()){
String jobId = job.getValue(String.class);
mDatabaseJobs.child(jobId).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
bid_count.addAndGet(1);
Вот структура базы данных, цель - как-то получить все рабочие места конкретного человека.
Есть ли способ получить сразу все вакансии? mabye список ключей? и не вызывать add-listener для каждого из них?
Если нет, я знаю, что firebase извлекает данные асинхронно, но делает ли это параллельно?
то есть в настоящее время мы увеличиваем атомарное целое число, чтобы узнать, все ли задания уже были получены от firebase, потому что мы не хотим, чтобы потоки одновременно увеличивали счетчик, необходимо ли это в нашей текущей реализации?
Спасибо!
Вы можете оставить HashMap вне поля «Пользователи», заполнить его списком заданий текущего пользователя. Затем прикрепите еще один слушатель к «Jobs» и переберите свою хэш-карту и выберите нужные вам задания. Ниже приведен справочный код:
HashMap<Integer, String> listOfJobs = new HashMap<>();
DatabaseReference mDatabaseUser = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUser.getUid()).child("listOfBids");
mDatabaseUser.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists) {
listOfJobs.putAll((Map) dataSnapshot.getValue());
}
// Here you can add a listener to the entire "Jobs" reference like this
DatabaseReference mDatabaseJobs = FirebaseDatabase.getInstance().getReference().child("Jobs");
mDatabaseJobs.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot userDataSnapshot) {
if (userDataSnapshot.exists) {
for (String jobId : listOfJobs.values()) {
if (userDataSnapshot.hasChild(jobId) {
DataSnapshot job = userSnapshot.child(jobId);
// here you can use job snapshot
bid_count.addAndGet(1); // something like this?
}
}
}
}
});
По сути, вы добавляете слушателя к чему-то, что не является вложенным или глубоким, и используете цикл для получения дочерних элементов вместо добавления слушателя к вложенным дочерним элементам.
Надеюсь это поможет.
разве вы не получаете всю базу данных вакансий только для одного пользовательского запроса? это звучит дорого, не так ли?
Не думаю, что это дорого. Firebase - это база данных реального времени на основе NoSQL. Он достаточно мощный, чтобы справиться с тем, что вы пытаетесь сделать. Вы не можете писать запросы и извлекать части своей базы данных. Вы можете попробовать реструктурировать свою базу данных, если хотите.
поправьте меня, если я ошибаюсь, но строка mDatabaseUser.addListenerForSingleValueEvent будет загружать всю базу данных заданий на клиентский телефон, независимо от того, насколько эффективна firebase
@DsCpp да, это извлекает все данные локально, и я не думаю, что это дорого. Если ваших данных в «Вакансиях» слишком много, вы можете снять лимит, добавив .limitToFirst(1000) или .limitToLast(500).
Добавьте структуру своей базы данных и укажите точную дату, которую вы хотите получить.