How to use orderByChild or orderByValue in a Fireb

2019-07-23 17:10发布

问题:

I'm looking for a way to get my data sorted into a RecyclerView. At this moment I'm using the priority method for this, but I know that it is better to apply a orderByChild or orderByValue method to achieve this. I just cannot find how to do this properly.

My (relevant) data structure is the following (bolt format):

path /events/{event}/GeneralInfo is GeneralInfo{}
path /events/{event}/instances/{instance} is Instance{}

type GeneralInfo {
    owner : KeyString,
    name : ShortNameString | Null, 
    color : Number | Null,
    description : NoteString | Null,
    shared : Boolean | Null,
    startDate : DateString,
    endDate : DateString, 
    instances: Map<KeyString, Boolean>,
    logoAvailable : Boolean | Null
}

type Instance {
    eventKey : KeyString,
    startDateTime : DateString,
    endDateTime : DateString,
    note : String | Null,
}

type KeyString extends String {
    validate() { this.length > 0 && this.length <= 255 }
}

type DateString extends String {
    validate() { this.length == 12 }
}

type ShortNameString extends String {
    validate() { this.length >= 0 && this.length <= 32 }
}

The FirebaseRecyclerAdapter is currently initialized as follows:

Query q = getGeneralInfo( eventKey ).child( "instances" ).orderByPriority();

mAdapter = new FirebaseRecyclerAdapter<Boolean, InstanceViewHolder>(Boolean.class, R.layout.instance_card, InstanceViewHolder.class, q) {
    @Override
    protected void populateViewHolder(final InstanceViewHolder viewHolder, Boolean model, final int position) {
       getInstanceByKey(mEventKey, refKey).addListenerForSingleValueEvent(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
             Instance i = dataSnapshot.getValue(Instance.class);
             ....

Note that I use an index key field (the field with the Boolean) to retrieve the actual data. The index field is currently sorted (using priorities).

I would like to sort directly on the instances (to make things less complicated and be able to remove the use of priorities).

p.s. Although it may seem that the data is not normalized, this is the case: the /events/{event} path is never used to retrieve data. This is only done to keep some overview.

回答1:

You don't need priorities if you already have a child with the value that you want to order on. From the comments it seems that your priority is the same value as the start date. In that case you can also order by that property:

Query q = getGeneralInfo( eventKey ).child( "instances" ).orderByChild("startDate");

You'll need to add an index to the instances:

"instances": {
  ".indexOn": "startDate"
}

Update

Apparently you're loading /events/{event}/GeneralInfo/instances, which you've defined as instances: Map<KeyString, Boolean>.

Since it's clear that you're looking to store a value, I'd change this to a Map<KeyString, Long> and then store the timestamp of the start date as the value in the index.

Then you can load/filter them in the correct order with orderByValue().