我是 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.");
}
});
}
}
Firebase实时数据库只能查询每个直接子节点下已知路径中的值。无法在
shop_syncs
列表中查询在其 userUids
属性下包含特定值的子节点,因为该值可能位于数组中的任何索引处。
更好的数据模型是将 UID 存储为地图,因为这样可以消除重复的可能性。所以:
userUids: {
"oH0v0NBQiXSiEiui18UVcF10J1K2": true
}
但即使使用这种结构,您也无法实现查询,因为您需要在规则中的
.indexOn
子句中命名每个可能的 UID。
实现用例的最佳方法是创建一个额外的顶级密钥,专门用于从 UID 映射到他们的商店:
shops_by_uid: {
"oH0v0NBQiXSiEiui18UVcF10J1K2": {
"shopId1": true,
"shopId2": true,
...
}
}
因此,使用此数据结构,您可以首先查找给定 UID 的商店 ID,然后再查找各个商店。
有关此类用例的更多信息,请参阅 Firebase 查询子级的子级是否包含值