Firebase 实时数据库:通过列表包含值进行查询

问题描述 投票:0回答:1

我是 Firebase RTDB 的新手。我正在开展一个学校项目,需要帮助。我有以下类存储在数据库中。

public class ShopSyncModel {

    private String uid = "";
    private String name = "";
    private String description = "";
    private List<String> userUids = new ArrayList<>();

    public ShopSyncModel() {
    }

    public ShopSyncModel(String uid, String name, String description, List<String> userUids) {
        this.uid = uid;
        this.name = name;
        this.description = description;
        this.userUids = userUids;
    }

    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("uid", uid);
        result.put("name", name);
        result.put("description", description);
        result.put("userUids", userUids);
        return result;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<String> getUserUids() {
        return userUids;
    }

    public void setUserUids(List<String> userUids) {
        this.userUids = userUids;
    }

    @NonNull
    @Override
    public String toString() {
        return "ShopSyncModel{" +
                "uid='" + uid + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", userUids=" + userUids +
                '}';
    }
}

存储到数据库中时,如下所示:

我想要获取“userUids”包含提供的 userUid 的所有 ShopSyncModel 实例。

@Singleton
public class ShopSyncsFirebaseReference {

    private static final String SHOP_SYNCS_COLLECTION = "shop_syncs";
    private static final String USER_UIDS_FIELD = "userUids";

    private final DatabaseReference shopSyncsCollection = FirebaseDatabase.getInstance()
            .getReference(SHOP_SYNCS_COLLECTION);

    // other methods removed here for brevity  
 
    public Task<DataSnapshot> getShopSyncsWithUserUid(String userUid) {
        Query query = shopSyncsCollection.orderByChild(USER_UIDS_FIELD).equalTo(userUid);
        return query.get();
    }

}

当我运行此查询时,没有返回任何内容。到目前为止我分享的内容有什么问题吗?我正在运行查询以填充回收器适配器。日志打印列表的大小为零。

public class MyShopSyncsActivity extends AppCompatActivity {

    // rest of code omitted for brevity

    @SuppressLint("NotifyDataSetChanged")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_shop_syncs);

        // check if the user is signed in
        FirebaseUser currentUser = checkIfUserIsLoggedInAndFetch(true);
        Log.d(TAG, "onCreate: user signed in with email " + currentUser.getEmail() + " and id (" +
                currentUser.getUid() + ")");

        // set up the recycler view
        List<ShopSyncModel> shopSyncs = new ArrayList<>();
        RecyclerView recyclerView = findViewById(R.id.recyclerViewShopSyncs);
        ShopSyncsRecyclerViewAdapter adapter =
                new ShopSyncsRecyclerViewAdapter(this, shopSyncs);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        applicationGraph.shopSyncsService()
                .getShopSyncsWithUserUid(currentUser.getUid())
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "onCreate: task for shop syncs is complete");

                        // gather all the shop syncs into a list
                        DataSnapshot dataSnapshot = task.getResult();
                        for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
                            // Convert each child's value into a ShopSyncModel object
                            ShopSyncModel shopSync = childSnapshot.getValue(ShopSyncModel.class);
                            if (shopSync != null) {
                                shopSyncs.add(shopSync);
                            }
                        }
                        Log.d(TAG, "onCreate: retrieved " + shopSyncs.size() + " shop syncs");

                        // notify the adapter that the data set has changed
                        adapter.notifyDataSetChanged();
                    } else {
                        signOutOnErrorAndRedirectToMainActivity("Failed to retrieve shop syncs. " +
                                                                        "Signing out now.");
                    }
                });
    }

}

日志显示用户uid与商店同步用户uid列表中的用户uid匹配。

android firebase-realtime-database
1个回答
0
投票

Firebase实时数据库只能查询每个直接子节点下已知路径中的值。无法在

shop_syncs
列表中查询在其
userUids
属性下包含特定值的子节点,因为该值可能位于数组中的任何索引处。


更好的数据模型是将 UID 存储为地图,因为这样可以消除重复的可能性。所以:

userUids: {
  "oH0v0NBQiXSiEiui18UVcF10J1K2": true
}

但即使使用这种结构,您也无法实现查询,因为您需要在规则中的

.indexOn
子句中命名每个可能的 UID。


实现用例的最佳方法是创建一个额外的顶级密钥,专门用于从 UID 映射到他们的商店:

shops_by_uid: {
  "oH0v0NBQiXSiEiui18UVcF10J1K2": {
    "shopId1": true,
    "shopId2": true,
    ...
  }
}

因此,使用此数据结构,您可以首先查找给定 UID 的商店 ID,然后再查找各个商店。


有关此类用例的更多信息,请参阅 Firebase 查询子级的子级是否包含值

© www.soinside.com 2019 - 2024. All rights reserved.