I have a database of 800+ items and I want to filter them by rarity. With "single" rarity (e.g only "legendary" rarity) I can easily do this, but the problem appears when trying to combine two rarities (e.g "event & basic" rarity).
This is the method I use:
private void loadFirebaseData(String rarity1, String rarity2) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Outfits");
reference.keepSynced(true);
Query query = reference.orderByChild("rarity").startAt(rarity1).endAt(rarity2);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
arrayCosmetics = new ArrayList<>();
for (DataSnapshot data : dataSnapshot.getChildren()) {
Cosmetics cosmetics = data.getValue(Cosmetics.class);
arrayCosmetics.add(cosmetics);
}
cosmeticsAdapter = new CosmeticsAdapter(getActivity(), arrayCosmetics);
cosmeticsAdapter.setHasStableIds(true);
recyclerView.setVisibility(View.VISIBLE);
recyclerView.setAdapter(cosmeticsAdapter);
Collections.shuffle(arrayCosmetics, new Random(3));
rootView.findViewById(R.id.progressBar).setVisibility(View.GONE);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
And calling it like: loadFirebaseData("basic", "event");
So the issue is that it loads me all the rarities from alphabetically "b" all the way to "e" (e.g "basic", "classic", "common", "elite", "epic") and obviously I want only "basic" and "event"
The database is structured like this:
"01" : {
"available" : "X",
"created" : "20191023",
"id" : 1,
"image" : "x",
"info" : "x",
"marketable" : true,
"name" : "xx",
"rarity" : "x",
"slot" : "xx" }
"02" : {
"available" : "x",
"created" : "20191023",
"id" : 1,
"image" : "x",
"info" : "x",
"marketable" : true,
"name" : "x",
"rarity" : "x",
"slot" : "x" }
Firebase rules:
"Outfits": {
".indexOn": ["rarity"]
}
It is possible to achieve what I want without loading the whole database in one big ArrayList<>()
?
If I have the whole ArrayList<>()
I can do something like this:
private void rarityFilter(String rarity1, String rarity2) {
ArrayList<Cosmetics> newListCosmetics = new ArrayList<>();
for (Cosmetics cosmetics : arrayCosmetics) {
String name = cosmetics.getRarity().toLowerCase();
if (name.contains(rarity1) || name.contains(rarity2))
newListCosmetics.add(cosmetics);
}
cosmeticsAdapter.setFilter(newListCosmetics);
}
But isn't it bad for performance to load the whole ArrayList<>()
?
It sounds like you're trying to load nodes whose rarity
property either have a value of event
or a value of basic
. The Firebase Realtime Database doesn't support such OR queries, nor are there a lot of good work-arounds to implement them.
The most common workarounds are:
"rarity_event_or_basic": true
and then filter for that. It's not great though, as it requires lots of properties, and becomes hard to index.ref.orderByChild("rarity").startAt("basic").endAt("event")
.Also see: