Запрос Firestore - проверка, существует ли уже имя пользователя

Мне нужна помощь с запросами Firestore. У меня есть all_users коллекция данных, пользовательские id-документы с информацией о каждом пользователе. образ базы данных firestore, я хочу проверить, существует ли уже имя пользователя. Я понимаю, как получить () документы и сравнить, как показано на их веб-странице, но как насчет запроса данных? Это мой код

обновление виджетов - (если текстовое поле mUser и текущее имя пользователя не совпадают)

 private void saveProfileSettings(){
    final String username = mUsername.getText().toString();
    //Case 1: user did not change their username
    if (!mUsers.getUsername().equals(username)){

        checkingIfusernameExist(username);

    }else {

    }
}

checkIfusernameExist метод

    private void checkingIfusernameExist(final String username){
    Log.d(TAG, "checkingIfusernameExist: Checking if " + username + " Exists");

    Query mQuery = mFirebaseFirestore.collection("all_users")
            .orderBy(getString(R.string.fields_username))
            .whereEqualTo("username", username);

    mQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

            if (documentSnapshots != null){
                Log.d(TAG, "onEvent: username does not exists");
                Toast.makeText(getActivity(), "Username is available", Toast.LENGTH_SHORT).show();
            }
            for (DocumentSnapshot ds: documentSnapshots){
                if (ds.exists()){
                    Log.d(TAG, "checkingIfusernameExist: FOUND A MATCH: " + ds.toObject(Users.class).getUsername());
                    Toast.makeText(getActivity(), "That username already exists.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    });
 }

Я не получаю ни ошибок, ни результатов. Я искал везде и не видел проблем как свои. Кроме того, вокруг не так много запросов, с которыми я могу работать. любые исправления будут оценены, заранее спасибо.

ОБНОВЛЕНИЕ: после нескольких дней поиска я действительно нашел решение с помощью ответов, которые я получил ниже. Итак, поскольку firestore не имеет операционной логики, и вы хотите обновить, если имя пользователя не существует с .whereEqualTo, используйте задачу поиска, содержащую любую полезную нагрузку.

код, который работал у меня

checkIfUsernameExists метод

private void checkingIfusernameExist(final String usernameToCompare){

    //----------------------------------------------------------------
    final Query mQuery = mFirebaseFirestore.collection("all_users").whereEqualTo("username", usernameToCompare);
    mQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            Log.d(TAG, "checkingIfusernameExist: checking if username exists");

            if (task.isSuccessful()){
                for (DocumentSnapshot ds: task.getResult()){
                    String userNames = ds.getString("username");
                        if (userNames.equals(usernameToCompare)) {
                            Log.d(TAG, "checkingIfusernameExist: FOUND A MATCH -username already exists");
                            Toast.makeText(getActivity(), "username already exists", Toast.LENGTH_SHORT).show();
                        }
                }
            }
            //checking if task contains any payload. if no, then update
            if (task.getResult().size() == 0){
                try{

                Log.d(TAG, "onComplete: MATCH NOT FOUND - username is available");
                Toast.makeText(getActivity(), "username changed", Toast.LENGTH_SHORT).show();
                //Updating new username............


                }catch (NullPointerException e){
                    Log.e(TAG, "NullPointerException: " + e.getMessage() );
                }
            }
        }
    });

person Seraware    schedule 01.02.2018    source источник


Ответы (3)


Чтобы решить эту проблему, используйте следующие строки кода:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference allUsersRef = rootRef.collection("all_users");
Query userNameQuery = allUsersRef.whereEqualTo("username", "userNameToCompare");
userNameQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            for (DocumentSnapshot document : task.getResult()) {
                if (document.exists()) {
                    String userName = document.getString("username");
                    Log.d(TAG, "username already exists");
                } else {
                    Log.d(TAG, "username does not exists");
                }
            }
        } else {
            Log.d("TAG", "Error getting documents: ", task.getException());
        }
    }
});

В котором userNameToCompare имеет тип String и является именем пользователя, с которым вы хотите провести сравнение.

person Alex Mamo    schedule 02.02.2018
comment
как будет выглядеть userNameToCompare ?. я понял ваш код. это просто логика для перебора всех имен пользователей, если отображается существующее имя пользователя. кажется, сравнивать документы легко, а не данные в документах. вы можете помочь с решением? Кстати, я вспомнил ваше имя пользователя из предыдущего вопроса. Я исправил это с помощью вашего решения. - person Seraware; 02.02.2018
comment
Как бы userNameToCompare выглядело? Это строка. Это имя, которое вводит пользователь, и вы хотите проверить, существует ли оно. Это userNameToCompare = mUsername.getText().trim().toString();. Я не понимаю. Разве ты не этого хочешь? Чтобы проверить, существует ли имя пользователя? - person Alex Mamo; 02.02.2018
comment
Чтение всех пользовательских документов, чтобы найти документ с определенным именем, довольно расточительно, как с точки зрения пропускной способности, так и с точки зрения платного чтения ($). Намного лучший подход - использовать запрос, как показывает Мохаммед в своем ответе. - person Frank van Puffelen; 24.12.2019
comment
@FrankvanPuffelen О, старый ответ. На самом деле запрос, скорее всего, будет использован. Еще раз спасибо, пуф! - person Alex Mamo; 24.12.2019

Следующий запрос возвращает всех пользователей с указанным usernameToCheck. Если имя пользователя уникально, вы получите только один документSnapShot.

    Query mQuery = mFirebaseFirestore.collection("all_users")
                .whereEqualTo("username", "usernameToCheck");

      mQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                for (DocumentSnapshot ds: documentSnapshots){
                    if (ds!=null){
               String userName = document.getString("username");
                        Log.d(TAG, "checkingIfusernameExist: FOUND A MATCH: " +userName );
                        Toast.makeText(getActivity(), "That username already exists.", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
person Mohammed Farhan    schedule 02.02.2018
comment
Как поступить, если не найдено повторяющееся имя пользователя? - person Seraware; 02.02.2018
comment
Предоставляете ли вы в своем приложении аутентификацию для входа в систему, например, Google auth? - person Mohammed Farhan; 02.02.2018
comment
есть аутентификация, но с адресом электронной почты и паролем. этот метод только проверяет, существует ли имя пользователя. он не включает еще одно заявление. или у вас есть метод, использующий ваш код? - person Seraware; 02.02.2018
comment
if (ds!=null) означает, что имя пользователя присутствует, вы можете использовать блок else, который сообщает, что ds is null, что означает отсутствие имени пользователя, подобного userNameToCheck. Вышеупомянутый метод является прямым и эффективным, поскольку он запрашивает только userNameToCheck во всех документах. Он вернет ds set, если совпадает с именем пользователя, иначе ds будет нулевым, что означает, что такого имени пользователя нет. Просто как тот!! - person Mohammed Farhan; 03.02.2018

Поскольку я не могу комментировать, я вместо этого набираю это как ответ:

Я хочу знать, как выглядят ваши журналы при запуске snapshotListener.

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

  • Log.d (TAG, «onEvent: имя пользователя не существует»);
  • Log.d (ТЕГ, "checkIfusernameExist: НАЙДЕН МАТЧ:" + ds.toObject (Users.class) .getUsername ());

Кроме того, вы написали, что у вас нет результата. Можно ли предположить, что вы ожидаете увидеть тосты, но не можете это сделать?

Кроме того, просмотрев ваш код, я добавил комментарии на основе эту документацию:

mQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
    @Override
    public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

        if (documentSnapshots != null){ 
        // you are checking here whether your querySnapshot is not null
        // instead of checking whether it is null or empty.
        // taking a wild guess here but could try to modify 
        // your if condition as follows -->
        // if (documentSnapshots.isEmpty()) {
            Log.d(TAG, "onEvent: username does not exists");
            Toast.makeText(getActivity(), "Username is available", Toast.LENGTH_SHORT).show();
        }
        // below as well documentSnapshots is assumed to be not null, 
        // hence all the more reason I am taking the above wild guess
        for (DocumentSnapshot ds: documentSnapshots){
            if (ds.exists()){
                Log.d(TAG, "checkingIfusernameExist: FOUND A MATCH: " + ds.toObject(Users.class).getUsername());
                Toast.makeText(getActivity(), "That username already exists.", Toast.LENGTH_SHORT).show();
            }
        }
    }
});

Я не могу продолжить отладку предоставленных вами данных. Но эта ссылка может вам больше помочь.

person Dhara Bhavsar    schedule 01.02.2018
comment
по какой-то причине (document.isEmpty ()) не кажется доступным для firestore, как это было в базе данных в реальном времени. в этом было бы немного больше смысла. я думал, что он сделает то же самое. в общем, я все еще просматриваю документацию и, возможно, придется пройти более грубую часть. ссылка, которую вы дали, может помочь. - person Seraware; 02.02.2018
comment
Да, в вашем случае для FireStore вам необходимо проверить переменную QuerySnapshot, то есть documentSnapshots.isEmpty() вместо document.isEmpty(), которая работает в базе данных реального времени. - person Dhara Bhavsar; 02.02.2018