Выберите случайную запись из базы данных Firebase Realtime в Java - PullRequest
0 голосов
/ 17 мая 2018

Я разрабатываю приложение для Android, которое включает в себя загрузку и загрузку изображений на сервер.Я использую Firebase для этой цели.Все изображения хранятся в хранилище Firebase, используя хэш изображения в качестве имени файла.Я также поддерживаю базу данных в реальном времени, которая хранит некоторую информацию о фотографиях.Мне нужно выбрать случайную картинку из хранилища, поэтому я решил выбрать случайную запись из базы данных.Я нашел этот ответ на SO (как вы видите, int написан на Javascript), который предлагает следующий код:

const numberOfUsers = 15;
const randomIndex = Math.floor(Math.random() * numberOfUsers);
var ref = firebase.database().ref('companies/01/users');
ref.limitToFirst(randomIndex).limitToLast(1).once('value').then(snapshot =>
{
    var user = snapshot.val();
    // do something with the user data
});

, но когда я пытаюсь построить подобный запрос в Java

imgref.limitToFirst(random + 1).limitToLast(1).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            randomHash = dataSnapshot.getKey();
            Log.e("get random name: ", randomHash);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

Я получаю сообщение об ошибке

Can't call limitToLast on query with previously set limit!

Так что, очевидно, я не могу использовать limitToFirst и LimitToLast в одном запросе.Итак, вот мой вопрос:

  1. Можно ли как-то использовать limitToFirst и limitToLast, чтобы использовать этот метод для получения случайной записи?

  2. Есть ли какой-либо другой способ получить случайную запись из базы данных Firebase Realtime без загрузки всей базы данных или итераций по ней (насколько я понимаю, итерация неэффективна, если я ошибаюсь, объясните, пожалуйста)

  3. Если это невозможно сделать из приложения, есть ли другой способ (например, с помощью облачных функций Firebase)

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Если вы не против добавления дополнительного ребенка в ваши данные, у вас есть несколько вариантов.

  1. Вы можете использовать транзакцию для нумерации каждого элемента при добавлении, а затем использовать случайное число с startAt(random).limitToFirst(1).
  2. Если вы хотите избежать транзакции, вы можете записать случайную длинную строку для каждого узла imgref. Тогда вы можете попробовать запросить сгенерированный случайный случай, например:

    ref.orderByChild("randomLong").startAt(newRandomLong).limitToFirst(1).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if(dataSnapshot.getChildrenCount() > 0){
                for(DataSnapshot snap : dataSnapshot.getChildren()){
                    //Do something with your random snapshot
                }
            }else
            {
             /*
             Handle case where the new random Long is after the range 
             currently in the database
             ref.orderByChild("randomLong").endAt(random).limitToLast(1)
             */
            }
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {
    
        }
    });
    

Обратите внимание, что # 2 добавит случайные веса к вашим значениям на основе случайных диапазонов между значениями. Этот эффект должен быть менее заметен в больших списках, но если вам нужен равномерный дистрибутив, вы, вероятно, захотите перейти с опцией №1.

Если вы не можете изменить свою текущую структуру данных, то я не уверен, что вы сможете обойти набор, как в ответе Алекса.

0 голосов
/ 18 мая 2018

Вам нужно знать, как ваша модель получает случайный ключ.Если это 1,2,3,4,5 идентификаторы, вы можете использовать его, как вы делаете, так что вы можете сравнить его.Лучший способ сделать это - сохранить все ключевые значения в массиве, выбрать случайное число с размером массива и выбрать индекс случайного числа.Их вы используете код из аналогичного ответа dataSnapshot.getKey();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...