Java 检查值是否已存在于Firebase中?

Java 检查值是否已存在于Firebase中?,java,android,firebase,android-layout,firebase-realtime-database,Java,Android,Firebase,Android Layout,Firebase Realtime Database,这是我的Firebase数据库结构。我想在大学中检查用户将要输入的新大学是否已经存在?问题是大学节点有随机密钥,所以我不知道如何检查大学的有效性? 如果大学已经存在,就不应该再写了 在当前结构中,您可以通过以下查询检查大学名称作为值存在于/universions下的频率: String name = "Comsats"; DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Univ

这是我的Firebase数据库结构。我想在大学中检查用户将要输入的新大学是否已经存在?问题是大学节点有随机密钥,所以我不知道如何检查大学的有效性? 如果大学已经存在,就不应该再写了


在当前结构中,您可以通过以下查询检查大学名称作为值存在于
/universions
下的频率:

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"
    }
    

    保证唯一性之前已经讨论过很多次,因此我建议您查看以下内容:

    • ,其中包含指向有关唯一性的更多问题的链接

    是的,它起作用了。我换了位置。。。我是大学的钥匙,但有一个小问题。。。。我想计算在数据库中注册的大学的数量,当同一所大学再次调用时,它们调用相同的键值并更改编号,有什么解决方案吗?这是一个新问题,但听起来像:1)您想在每个键值下存储名称和计数,2)然后使用
    ServerValue.increment(1)
    以增加值。如果你很难做到这一点,我建议你发布一个新的问题,说明你尝试了什么,以及你遇到了什么困难。