Firebase实时数据库查询问题

时间:2020-03-23 21:31:07

标签: android firebase firebase-realtime-database

我有一个800多个商品的数据库,我想按稀有性过滤它们。使用“单个”稀有性(例如,只有“传奇”稀有性),我可以轻松地做到这一点,但是当尝试将两种稀有性(例如“事件和基本”稀有性)组合在一起时,就会出现问题。

这是我使用的方法:

 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) {
        }
    });
}

并像这样调用它:loadFirebaseData("basic", "event");

所以问题是它把所有稀有的东西从字母“ b”一直加载到“ e”(例如“基本”,“经典”,“通用”,“精英”,“史诗”),显然我只想要“基本”和“事件”

数据库的结构如下:

"01" : {
"available" : "Wanderer Crate",
"created" : "20191023T021358Z",
"id" : 11010006,
"image" : "https://prod-live-front.playbattlegrounds.com/images/item_176/11010006.png",
"info" : "Drop Chance: 5.00%",
"marketable" : true,
"name" : "Dirty Tank Top (White)",
"rarity" : "common",
"slot" : "torso" }

"02" : {
"available" : "Wanderer Crate",
"created" : "20191023T021358Z",
"id" : 11010014,
"image" : "https://prod-live-front.playbattlegrounds.com/images/item_176/11010014.png",
"info" : "Drop Chance: 5.00%",
"marketable" : true,
"name" : "Tank Top (Charcoal)",
"rarity" : "common",
"slot" : "torso" }

Firebase规则:

 "Outfits": {
  ".indexOn": ["rarity"]
}

是否可以在不将整个数据库加载到一个大ArrayList<>()中的情况下实现我想要的?

如果我拥有整个ArrayList<>(),我可以做这样的事情:

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);
}

但是加载整个ArrayList<>()是否对性能不利?

1 个答案:

答案 0 :(得分:0)

听起来好像您正在尝试加载其rarity属性值为event或值为basic的节点。 Firebase实时数据库不支持此类OR查询,也没有很多好的解决方法来实现它们。

最常见的解决方法是:

  • 为您要允许的每个组合添加一个属性,例如"rarity_event_or_basic": true,然后对此进行过滤。不过,它并不是很好,因为它需要很多属性,并且很难索引。
  • 对每个值执行单独的查询,然后将结果合并到您的应用程序代码中。就性能而言,这非常有效,因为Firebase可以并行执行它们。但是代码通常有点费解,如果您想将其与限制过滤器结合使用,最终可能会检索到比所需更多的数据。
  • 如果在字典上这些值彼此接近,则可以使用范围条件。例如。 ref.orderByChild("rarity").startAt("basic").endAt("event")

另请参阅: