2016-09-27 5 views
5

Я новичок в Firebase и NoSQL. У меня есть Android Demo с текстовым полем Autocomplete City, в котором я хочу заполнить города, которые у меня есть, из моей базы данных Firebase при наборе текста.Извлечение данных из базы данных Firebase Realtime в Android

{ "cities":{ 
     "Guayaquil":true, 
     "Gualaceo":true, 
     "Quito":true, 
     "Quevedo":true, 
     "Cuenca":true, 
     "Loja":true, 
     "Ibarra":true, 
     "Manta":true 
    } 
} 

Это то, что у меня есть до сих пор.

Как я могу получить из городов БД, которые начинаются с буквы (ввод с клавиатуры)? Если я начну печатать «G», я хочу получить «Guayaquil» и «Gualaceo».

Если я использую orderByValue, он всегда возвращает пустой снимок.

Если я использую orderByKey, то верните весь список.

Query citiesQuery = databaseRef.child("cities").startAt(input).orderByValue(); 
    citiesQuery.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      List<String> cities = new ArrayList<String>(); 
      for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { 
       cities.add(postSnapshot.getValue().toString()); 
      } 

Примечание: Если вы можете порекомендовать лучшую структуру данных, вы радушны.

+0

Насколько велика эта база данных городов будет? Было бы правдоподобным для вашего приложения читать в базе данных один раз в локальной копии (например, какой-то массив), а затем использовать локальную логику, чтобы отображать только соответствующие значения при наборе текста? – Ryan

+0

Изначально это будет около 10, но может увеличиться до 100. Я хотел, чтобы эта функция была «онлайн», поэтому я могу добавлять новые города, не требуя их локального хранения. –

+0

О, это хорошо. Что касается процессора и сети, то 100 небольших струн практически ничего не стоят, так что это определенно будет быстро. Позвольте мне пояснить, что я имею в виду, сохраняя его локально. Я имею в виду в памяти во время выполнения, вот и все. Я не хочу хранить копию в хранилище устройств или что-то в этом роде. Все, что я имею в виду, это чтение городов в массив, а затем работа с этим массивом для отображения данных. Когда база данных изменяется, вы можете очень легко обновить массив почти мгновенно, но я сомневаюсь, что он будет меняться часто. Проверьте мой ответ, чтобы немного объяснить, о чем я думал. – Ryan

ответ

6

@NicholasChen выявил проблему. Но вот то, как вы реализуете, используя 3.х SDK:

DatabaseReference cities = databaseRef.child("cities") 
Query citiesQuery = cities.orderByKey().startAt(input).endAt(input+"\uf8ff"); 
citiesQuery.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     List<String> cities = new ArrayList<String>(); 
     for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { 
      cities.add(postSnapshot.getValue().toString()); 
     } 

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

Для относительно коротких списков предметов подход Райана также будет работать нормально , Но вышеупомянутый запрос Firebase будет фильтровать серверную сторону.

Update

Я просто побежал этот код:

DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference("39714936"); 

    String input = "G"; 

    DatabaseReference cities = databaseRef.child("cities"); 
    Query citiesQuery = cities.orderByKey().startAt(input).endAt(input + "\uf8ff"); 
    citiesQuery.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      List<String> cities = new ArrayList<String>(); 

      for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) { 
       cities.add(postSnapshot.getValue().toString()); 
      } 
      System.out.println(cities); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 

И распечатанный:

истинного

истинного

Так Клио rly соответствует двум городам.

Не стесняйтесь проверить на моей базе данных: https://stackoverflow.firebaseio.com/39714936

+0

Он возвращает пустой снимок –

+0

Я тестировал и работает для меня. Я добавил полный фрагмент и ссылку на мою базу данных на вопрос. –

+0

Я тестировал его и отлично работает –

0

Конечно, OrderByValue ничего не возвращает, потому что это логические значения, которые у вас есть.

Вы можете использовать методы startAt и endAt для этого. (Внизу Firebase 2.0 в код)

var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs"); 
ref.orderByKey().startAt("b").endAt("b\uf8ff").on("child_added", function(snapshot) { 
    console.log(snapshot.key()); 
}); 

Вы можете исследовать больше на сайте документации here Firebase 3.

Что сделал Райан, было правильно. Тем не менее, вы должны реализовать startAt в dataSnapshot, чтобы убедиться, что ваш «живой» поиск работает.

+0

код необходим для Android-приложения –

+0

Вот почему это помечено в Android ?? – Nicholas

+0

Я не думаю, что вы используете startAt с моим методом, потому что я выполняю запрос, я назначаю слушателя в режиме реального времени для прослушивания любых изменений в базе данных. – Ryan

1

Попробуйте что-то подобное, чтобы перебрать детей в cities моментальный снимок и добавить все города в ArrayList из Strings.

ArrayList<String> cityList = new ArrayList<>(); 

databaseRef.child("cities").addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     cityList.clear(); 
     for (DataSnapshot data : dataSnapshot.getChildren()){ 
      cityList.add(data.getKey); 
     } 

    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 
     Log.w(TAG, "getUser:onCancelled", databaseError.toException()); 
     // ... 
    } 
}); 

Редактирование этого пункта для ясности:

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

Логика в моей голове что-то вроде:

  1. Установите значение слушателя в текстовом поле.
  2. Когда пользователь вводит тип, создайте представление, отображающее все элементы в списке массивов , которые начинаются с той же подстроки, которая была введена.
  3. Ручка arrayIndex ошибки, конечно.

Надеемся, это поможет вам на правильном пути. Я уверен, что есть другие способы его реализации, но это то, что я лично сделал бы. Если вам нужна помощь с кодом для отображения правильных городов, запустите чат со мной, и я смогу провести мозговой штурм с вами.

+0

Я вижу вашу точку зрения, но я хотел сохранить эту функцию «автозаполнения» в сети, чтобы я мог добавлять или удалять города, без необходимости хранить их локально. –

+1

Он все равно будет онлайн, как я это делаю. Независимо от того, что вы делаете, вам придется прочитать некоторые данные в переменной в какой-то момент, или ваше приложение не сможет отобразить название города. Он по-прежнему будет поддерживать онлайн-удаление, и если кто-то удалит город во время ввода другого пользователя, он все равно обновит список других пользователей при наборе текста. Я думаю, что я мог бы объяснить слушателю неправильно, или, может быть, я просто не понимаю требования. – Ryan

+0

Я предполагаю, что ваш подход правильный. Но идея mi заключалась в том, чтобы отправить Firebase первые буквы города, а в «Снимок» получить список только городов, начинающихся с этих букв. –

Смежные вопросы