【问题标题】:Checking if a particular value exists in the Firebase database检查 Firebase 数据库中是否存在特定值
【发布时间】:2018-06-02 06:19:41
【问题描述】:

我正在使用Firebase 实时数据库制作一个Android 应用程序。当新用户在我的应用上注册时,该用户的数据将保存在 Firebase 数据库中。

用户必须提供以下详细信息才能注册:

  1. 全名
  2. 电子邮件
  3. 用户名
  4. 密码

数据库结构

每当新用户尝试注册时,我必须确保每个用户的用户名都是唯一的,因此我会检查数据库中用户输入的username 是否已存在于数据库中。

为此,我编写了以下方法:

private boolean usernameExists(String username) {
     DatabaseReference fdbRefer = FirebaseDatabase.getInstance().getReference("Users/"+username);
     return (fdbRefer != null);
}

我在这个方法背后的逻辑是,如果getReference方法找不到对指定路径的引用,它将返回null,以便我可以返回fdbRefer是否为null。如果fdbRefernull,则表示username在数据库中不存在。

问题

这个方法的问题是,无论输入的username是否存在于数据库中,它总是返回true。这让我相信fdbRefer 永远不是null

这让我想到了我的问题......

问题

getReference 方法在firebase 数据库中找不到指定路径时返回什么以及检查username 是否已存在于数据库中的正确方法是什么?

【问题讨论】:

    标签: java android firebase firebase-realtime-database


    【解决方案1】:

    要检查用户的存在,请使用以下代码:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference userNameRef = rootRef.child("Users").child("Nick123");
    ValueEventListener eventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if(!dataSnapshot.exists()) {
                //create new user
            }
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
        }
    };
    userNameRef.addListenerForSingleValueEvent(eventListener);
    

    您也可以使用 Query 来实现相同的目的:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    Query query = rootRef.child("Users").orderByChild("userName").equalTo("Nick123");
    query.addValueEventListener(/* ... */);
    

    这是另一种循环整个Users 节点的方法,但不只是使用对单个用户的直接引用。当您使用 uid 而不是用户名(就像您现在所做的那样)作为用户之间的唯一标识符时,更有可能使用此选项。因此,如果您的数据库结构可能与此类似:

    Firebase-root
       |
       --- Users
            |
            --- uid
                 |
                 --- userName: "Test User"
                 |
                 --- emailAddress: "user@email.com"
    

    第二种解决方案是推荐的。

    还有另一种解决方案,您需要创建另一个名为userNames 的节点,您只能在其中保存唯一的用户名。另请参阅下面的相应安全规则:

    "Users": {
      "$uid": {
        ".write": "auth !== null && auth.uid === $uid",
        ".read": "auth !== null && auth.provider === 'password'",
        "userName": {
          ".validate": "
            !root.child('userNames').child(newData.val()).exists() ||
            root.child('userNames').child(newData.val()).val() == $uid"
        }
      }
    }
    

    但是由于在这种情况下,您的用户名已经是节点的名称,我建议您继续使用第一个。

    【讨论】:

    • 另请参阅这两种方法之间的区别。使用第一个解决方案将帮助您节省带宽。
    • 你能解释一下if(!dataSnapshot.exists())是干什么用的吗?
    • dataSnapshot 对象表示以下位置的快照:Firebase-root -> Users -> Nick123。最好的解决方案是直接在dataSnapshot 上使用exists() 方法来检查是否存在。当您使用查询时,您正在循环整个对象,这意味着浪费带宽。我还给了你查询解决方案,也许你将来会需要。
    • @RedM 第一个解决方案是使用直接指向特定用户的引用,而第二个解决方案是使用搜索整个对象以查找相应用户的查询。
    • @MehulTank 在这种情况下,您应该使用彼得的答案。
    【解决方案2】:

    试试这个:

    DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Users");
    ref.orderByChild("username").equalTo(Nick123).addValueEventListener(new ValueEventListener(){
      @Override
      public void onDataChange(DataSnapshot dataSnapshot){
          if(dataSnapshot.exist() {
             //username exist
              }
            }
    

    您必须使用orderbychildequalto 来检查值是否存在。 如果您不使用orderbychildequalto,那么它只会检查username 子节点是否存在并且不关心值。

    这个orderByChild("username").equalTo(Nick123)就像在说:

    WHERE username=Nick123
    

    【讨论】:

      【解决方案3】:

      非常适合我

      DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
              Query query = reference
                      .child(getString(R.string.dbname_users))
                      .orderByChild("username")
                      .equalTo(username);
              query.addListenerForSingleValueEvent(new ValueEventListener() {
                  @Override
                  public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                      if(dataSnapshot.getChildrenCount()>0) {
                          //username found
      
                      }else{
                          // username not found
                      }
      
                  }
                  @Override
                  public void onCancelled(DatabaseError databaseError) {
      
                  }
              });
      

      【讨论】:

        【解决方案4】:

        您可以使用 orderBy 查询来检查用户名是否已经存在,而不是检查引用是否存在

        orderByChild('username').equalTo(username) 如果某些数据已经存在,则查询将返回数据,否则将返回 null。

        【讨论】:

          【解决方案5】:

          这样检查...

              fdbRefer.addListenerForSingleValueEvent(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
          if(dataSnapshot.exist() {
          //username exist
          }
          else {
          //username doesn't exist
          }
          }
          });
          

          【讨论】:

            【解决方案6】:

            由于您已经找到了解决问题的方法,我将尝试解释为什么您的代码无法正常工作。

             DatabaseReference fdbRefer = FirebaseDatabase.getInstance().getReference("Users/"+username);
            

            您可能会认为,如果数据库中不存在“Users/”+用户名,则上述语句中的fdbRefer 将为空。
            但实际上,这条语句只会存储getReference()中指定字段的路径。因此,当您检查 fdbRef!=null 时,它始终是正确的,因为 fdbRefer 将持有类似“https://.firebase.com/Users/Nick123”的值。

            【讨论】:

              猜你喜欢
              • 2020-07-31
              • 2016-10-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-09-21
              • 1970-01-01
              • 1970-01-01
              • 2021-01-14
              相关资源
              最近更新 更多