будет содержать значение что-то вроде 'https: //.firebase.com/Users/Nick123.

аю приложение для Android, используяFirebase база данных в реальном времени. Когда новый пользователь регистрируется в моем приложении, данные этого пользователя сохраняются в базе данных Firebase.

Пользователь должен предоставить следующие данные для регистрации:

Полное имяЭлектронное письмоимя пользователяпарольСтруктура базы данных

Всякий раз, когда новый пользователь пытается зарегистрироваться, я должен убедиться, что имя пользователя каждого пользователя уникально, поэтому я проверяю базу данных, еслиusername введенный пользователем уже существует в базе данных или нет.

Для этого я написал следующий метод:

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

Моя логика этого метода заключается в том, что еслиgetReference метод не может найти ссылку на указанный путь, он возвратит нуль, чтобы я мог вернутьfdbRefer являетсяnull или нет. ЕслиfdbRefer являетсяnullтогда это означает, чтоusername не существует в базе данных.

проблема

Проблема с этим методом в том, что он всегда возвращаетtrue был ли введенusername существует в базе данных или нет. Что заставило меня поверить, чтоfdbRefer никогдаnull.

Это подводит меня к моему вопросу ...

Вопрос

Что значитgetReference возврат метода, когда он не может найти указанный путь вfirebase базы данных и как правильно проверить, еслиusername уже существует в базе данных или нет?

Ответы на вопрос(5)

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

Вы должны использоватьorderbychild а такжеequalto проверить значение, если оно есть. Если вы не используетеorderbychild а такжеequalto тогда он просто проверит,username дочерний узел существует и не заботится о значении.

этоorderByChild("username").equalTo(Nick123) это как сказать:

WHERE username=Nick123

я постараюсь объяснить, почему ваш код не работал.

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

Вы можете подумать, что в приведенном выше заявленииfdbRefer будет нулевым, если «Users /» + username отсутствует в базе данных.
Но на самом деле этот оператор будет хранить только путь к указанному полю вgetReference(), Поэтому, когда вы проверяетеfdbRef!=nullэто всегда так, потому чтоfdbRefer будет содержать значение что-то вроде 'https: //.firebase.com/Users/Nick123.

Проверьте это так ...

    fdbRefer.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exist() {
//username exist
}
else {
//username doesn't exist
}
}
});
Решение Вопроса

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: "[email protected]"

Второе решение является рекомендуемым.

Существует также другое решение, которое включает в себя создание другого узла с именем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"
    }
  }
}

Но так как в этом случае ваше имя пользователя уже является именем узла, я рекомендую вам продолжить с первым.

 Alex Mamo19 дек. 2017 г., 20:34
Пожалуйста, посмотрите также разницу между этими двумя подходами. Использование первого решения поможет вам сэкономить трафик.
 Alex Mamo19 сент. 2018 г., 22:08
@RedM Первое решение использует ссылку, которая указывает непосредственно на конкретного пользователя, а второе использует запрос, который ищет весь объект, чтобы найти соответствующего пользователя.
 ninbit09 авг. 2018 г., 18:29
@AlexMamo для первого решения, что если пользовательский узел имеет push-токены перед именем пользователя, например, когда мы добавляем пользователей методом push (). Я думаю, что мой dataSnapShot всегда становится нулевым из-за этого
 Nick19 дек. 2017 г., 20:35
Можете ли вы объяснить, чтоif(!dataSnapshot.exists()) это для ?
 Alex Mamo19 дек. 2017 г., 20:44
dataSnapshot Объект представляет собой снимок в следующем месте:Firebase-root -> Users -> Nick123, Лучшее решение - использоватьexists() Метод непосредственно наdataSnapshot проверить на существование. Когда вы используете Query, вы проходите через весь объект, а это означает потерю пропускной способности. Я дал вам также решение Query, возможно, оно понадобится вам в будущем.

y, чтобы проверить, существует ли имя пользователя уже

Запрос orderByChild ('username'). equalTo (username) вернет данные, если некоторые данные уже существуют, в противном случае он вернет null.

Ваш ответ на вопрос