Firebase и фильтрация по значению / ключу - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть следующая структура в Firebase:

enter image description here

Я хотел бы получить только даты, попадающие в данный диапазон, и для этого яиспользовал следующий return getMealsRefForUser().orderByValue().equalTo("2018-11-17");, где ссылка mealsRefForUser= firebaseDatabase.getReference(MEALS_OF).child(user.getUid());.Однако фильтрация не происходит.Чего мне не хватает?

РЕДАКТИРОВАТЬ: Итак, я всегда получаю /mealsOf/<userId> узел, даже если я квалифицирую его на orderByKey().startAt().endAt(), хотя моя цель - получить снимок данных, который содержит несколько узловчей <year>-<month>-<day> «тег» находится в заданном диапазоне.

РЕДАКТИРОВАТЬ: я пытаюсь достичь, это привязать LiveData к запросу, подобному этому:

public FirebaseQueryLiveData( Constraints c ) {
    if ( c == null )
        this.query= FirebaseDatabase.getInstance()
            .getReference("/mealsOf")
            .child(FirebaseAuth.getInstance().getCurrentUser().getUid());
    else
        this.query= FirebaseDatabase.getInstance()
            .getReference("/mealsOf")
            .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
            .orderByKey().startAt(c.dayFrom).endAt(c.dayTo);
}

Но этов конечном итоге дает мне весь список, все то же самое - независимо от ограничений.Весь исходный код класса:

// https://firebase.googleblog.com/2017/12/using-android-architecture-components.html
public class FirebaseQueryLiveData extends LiveData<DataSnapshot> {

    private static final String TAG = "FirebaseQueryLiveData";
    private boolean listenerRemovePending= false;
    private final Handler handler= new Handler();

    private final Runnable removeListener= new Runnable() {
        @Override
        public void run() {
            query.removeEventListener(listener);
            listenerRemovePending= false;
        }
    };

    private static final String LOG_TAG= "FirebaseQueryLiveData";

    private final Query query;
    private final InnerValueEventListener listener= new InnerValueEventListener();

    public FirebaseQueryLiveData( Constraints c ) {
        if ( c == null )
            this.query= FirebaseDatabase.getInstance()
                .getReference("/mealsOf")
                .child(FirebaseAuth.getInstance().getCurrentUser().getUid());
        else
            this.query= FirebaseDatabase.getInstance()
                .getReference("/mealsOf")
                .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                .orderByKey().startAt(c.dayFrom).endAt(c.dayTo);
    }

    public FirebaseQueryLiveData( DatabaseReference ref ) {
        this.query= ref;
    }

    @Override
    protected void onActive() {
        //Log.d(LOG_TAG, "onActive");
        if ( listenerRemovePending )
            handler.removeCallbacks(removeListener);
        else
            query.addValueEventListener(listener);
        listenerRemovePending= false ;
    }

    @Override
    protected void onInactive() {
        //Log.d(LOG_TAG, "onInactive");
        handler.postDelayed(removeListener,2000);
        listenerRemovePending= true ;
        //query.removeEventListener(listener);
    }

    private class InnerValueEventListener implements ValueEventListener {
        @Override
        public void onDataChange( @NonNull DataSnapshot dataSnapshot ) {
            setValue(dataSnapshot);
        }
        @Override
        public void onCancelled( @NonNull DatabaseError databaseError ) {
            Log.e(LOG_TAG, "Can not listen to query " + query,databaseError.toException());
        }
    }
}

Мне кажется, я знаю, что происходит.У меня есть этот кусок в моем коде: viewModel= ViewModelProviders.of(this, new CustomViewModelFactory(c)) .get(MealListViewModel.class);

Это не срабатывает, когда я поставляю новые ограничения запроса.Означает ли это, что я могу получить только один viewmodelprovider за один прогон моего приложения?

РЕДАКТИРОВАТЬ: В приведенном выше обновленном изображении под meals дочерним элементом даты у меня есть деление по часам - например, 20 будучи 8PM и т. д. Как бы я ограничил свой запрос обеими осями - днями и часами?Прежде чем я услышу (я должен признать соответствующие) комментарии, которые мне нужны для реструктуризации схемы базы данных, я хотел бы знать, возможно ли это.Нужно ли нам что-то вроде следующего?

 return await dbroot.ref(`mealsOf/${userId}`)
        .orderByKey().startAt(dayFrom).endAt(dayTo)
        .orderByChild("meals")
        .startAt(`${hourFrom}:00`).endAt(`${hourTo}:59`)

Или, в качестве альтернативы, я должен оставить другое место, например duplicate/{userId}/{day}/{hour}, для включения запросов, таких как

return await dbroot.ref(`duplicate/${userId}`)
            .orderByKey().startAt(dayFrom).endAt(dayTo)
            .orderByKey()
            .startAt(`${hourFrom}:00`).endAt(`${hourTo}:59`)

1 Ответ

0 голосов
/ 19 ноября 2018

Вы не должны использовать запрос, чтобы получить этот ключ. Запросы используются, если вы хотите вернуть список, или если вы не знаете точный путь, по которому вы пытаетесь добраться.

Как вы знаете uid и date, вы можете напрямую запросить объект.

JavaScript:

getMealsRefForUser(userId, date) {
  return firebase.database().ref(`/mealsOf/${userId}/${date}`);
}

Android:

DatabaseReference root = FirebaseDatabase.getInstance().getReference("mealsOf");
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
return root.child(uid).child("2018-11-17");

В противном случае, если вы хотите сделать запрос, вы должны использовать методы startAt или endAt.

JavaScript:

getMealsRefForUser(userId, startDate) {
  return firebase.database().ref(`/mealsOf/${userId}`).orderByKey().startAt(startDate);
}

Android:

return root.orderByKey().startAt("2018-11-17");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...