【发布时间】:2020-12-30 20:16:39
【问题描述】:
【问题讨论】:
标签: java android firebase android-layout firebase-realtime-database
【问题讨论】:
标签: java android firebase android-layout firebase-realtime-database
在您当前的结构中,您可以使用如下查询来检查大学名称作为 /Universities 下的值存在的频率:
String name = "Comsats";
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Universities");
ref.orderByValue().equalTo(name).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("Firebase", "There are "+dataSnapshot.getChildrenCount()+" universities named "+name);
for (DataSnapshot universitySnapshot: dataSnapshot.getChildren()) {
Log.i("Firebase", universitySnapshot.getKey+": "+universitySnapshot.getValue(String.class));
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
或者只是为了检查它是否存在,这会稍微简单/更快:
ref.orderByValue().equalTo(name).limitToFirst(1).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.i("Firebase", "University "+name+" already exists");
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
如果您使用上述方法然后添加大学,您最终会遇到竞争条件。当一个客户端检查名称是否已经存在时,另一个客户端可能正在添加它。由于不能保证这些操作按您希望的顺序进行,因此您仍然可能最终得到两所同名的大学。
防止这种情况的唯一方法是使用大学名称作为节点的键*,而不是作为值。您的结构将变为:
"Universities": {
"University of Haripu": true,
"Comsats": true,
"UET": true
}
节点键在特定位置保证是唯一的,因为无法插入第二个同名的子节点。因此,使用这种结构,您可以自动保证数据结构中的唯一性要求。
true 值在上述结构中没有特定含义,只是因为 Firebase 无法存储没有值的键。如果你有更有意义的价值,你也可以使用它。事实上,你可能不得不这样做......
Firebase 有一些字符不允许出现在节点键中,而这些字符允许出现在值中。如果您的值可能包含这样的值,则您需要对用户输入的值执行一些编码,并将其转换为您为大学存储的密钥。
两种常见的编码是:
第一种方法会导致更多可识别的键,所以我将在这里使用它。在实践中,第二种方法通常在代码中更好更简单,因为如今散列是相当标准的功能,而其他编码可能会为您的用例或 Firebase 定制。
在这两种情况下,您都需要存储用户输入的实际值。所以说空格和大写字符不允许用于键(它们都是都允许的,所以这只是一个说明性的例子),你最终会得到:
"Universities": {
"universityofharipu": "University of Haripu",
"comsats": "Comsats",
"uet": "UET"
}
保证唯一性之前已经讨论过很多次了,所以我推荐看看这些:
【讨论】:
ServerValue.increment(1) 增加值。如果您在完成这项工作时遇到问题,我建议您发布一个新问题,说明您尝试过的内容以及遇到的问题。