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.
@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.
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
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:
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.
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.