web-dev-qa-db-fra.com

Récupération de données de la base de données Firebase Realtime sous Android

Je suis nouveau sur Firebase et NoSQL. J'ai une démo Android, avec un champ de texte City Autocomplete dans lequel je souhaite renseigner les villes que j'ai depuis ma base de données Firebase, lors de la frappe.

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

C'est ce que j'ai jusqu'ici.

Comment puis-je extraire des villes de la base de données commençant par une lettre (saisie au clavier)? Si je commence à taper "G", je souhaite recevoir "Guayaquil" et "Gualaceo".

Si j'utilise orderByValue, retourne toujours un instantané vide. 

Si j’utilise orderByKey, retourne la liste complète. 

    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());
            }

Remarque: Si vous pouvez recommander une meilleure structure de données, vous êtes le bienvenu.

5
Erick Medina

@NicholasChen a identifié le problème. Mais voici comment vous utiliseriez le SDK 3.x:

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());
        }

En commençant par la saisie de l'utilisateur et en terminant par la dernière chaîne commençant par la saisie de l'utilisateur, vous obtenez tous les éléments correspondants.

Pour des listes relativement courtes d'éléments, l'approche de Ryan fonctionnera également bien. Mais la requête Firebase ci-dessus va filtrer côté serveur.

Mettre à jour

Je viens de lancer ce code:

    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) {

        }
    });

Et cela imprimé:

vrai

vrai

Donc correspond clairement à deux villes.

N'hésitez pas à tester ma base de données: https://stackoverflow.firebaseio.com/39714936

6
Frank van Puffelen

Essayez quelque chose comme ceci pour parcourir les enfants dans l'instantané cities et ajouter toutes les villes à une ArrayList de 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());
        // ...
    }
});

Modification de ce paragraphe pour plus de clarté:

Ainsi, toutes vos villes seront lues dans la mémoire du programme afin que vous puissiez utiliser ces données pour afficher les villes à l'utilisateur. Si la liste des villes change, les données affichées par l'utilisateur le seront également. Si l'utilisateur n'est pas en ligne, cela ne fonctionnera pas. Cela met un auditeur en ligne uniquement sur la base de données en temps réel. 

La logique dans mon esprit est quelque chose comme:

  1. Définissez un écouteur de valeur dans la zone de texte.
  2. Lorsque l'utilisateur tape, faites en sorte que la vue affiche tous les éléments de la liste de tableaux Qui commencent par la même sous-chaîne que celle qui a été tapée.
  3. Traiter les erreurs de arrayIndex bien sûr.

J'espère que cela vous mettra sur la bonne voie. Je suis sûr qu'il existe d'autres moyens de le mettre en œuvre, mais c'est ce que je ferais personnellement. Si vous avez besoin d'aide avec le code pour afficher les villes correctes, commencez une discussion avec moi et je pourrai réfléchir avec vous.

1
Ryan

Bien sûr, OrderByValue ne renvoie rien car c'est le booléen que vous avez.

vous pouvez utiliser les méthodes startAt et endAt pour le faire. (Ce qui suit est le code de 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());
});

Vous pouvez en savoir plus sur le site de documentation de Firebase 3 ici .

Ce que Ryan a fait était bien. Cependant, vous devez implémenter startAt sur le dataSnapshot pour vous assurer que votre recherche "en direct" fonctionne.

0
Nicholas