{
"movies": {
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson"
},
"movie2": {
"genre": "Horror",
"name": "The Shining",
"lead": "Jack Nicholson"
},
"movie3": {
"genre": "comedy",
"name": "The Mask",
"lead": "Jim Carrey"
}
}
}
Je suis un débutant Firebase. Comment puis-je récupérer un résultat à partir des données ci-dessus où genre = 'comedy'
AND lead = 'Jack Nicholson'
?
Quelles sont mes options?
En utilisant API de requête de Firebase , vous pourriez être tenté d'essayer ceci:
// !!! THIS WILL NOT WORK !!!
ref
.orderBy('genre')
.startAt('comedy').endAt('comedy')
.orderBy('lead') // !!! THIS LINE WILL RAISE AN ERROR !!!
.startAt('Jack Nicholson').endAt('Jack Nicholson')
.on('value', function(snapshot) {
console.log(snapshot.val());
});
Mais comme le dit @RobDiMarco de Firebase dans les commentaires:
plusieurs appels
orderBy()
généreront une erreur
Donc mon code ci-dessus ne fonctionnera pas .
Je connais trois approches qui fonctionneront.
Ce que vous pouvez faire, c'est exécuter un orderBy().startAt()./endAt()
sur le serveur, déroulez les données restantes et filtrez-le dans le code JavaScript de votre client.
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
Si cela ne suffit pas, vous devriez envisager de modifier/développer vos données pour permettre votre cas d'utilisation. Par exemple: vous pouvez insérer genre + lead dans une propriété unique que vous utilisez simplement pour ce filtre.
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
Vous construisez ainsi votre propre index multi-colonnes et pouvez l'interroger avec:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East a écrit un bibliothèque appelée QueryBase qui aide à générer de telles propriétés .
Vous pouvez même faire des requêtes relatives/plage, disons que vous voulez autoriser l’interrogation de films par catégorie et par année. Vous utiliseriez cette structure de données:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
Et ensuite, recherchez les comédies des années 90 avec:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Si vous devez filtrer sur plus que l'année, veillez à ajouter les autres éléments de date dans l'ordre décroissant, par exemple. "comedy_1997-12-25"
. Ainsi, l'ordre lexicographique que Firebase applique aux valeurs de chaîne sera le même que l'ordre chronologique.
Cette combinaison de valeurs dans une propriété peut fonctionner avec plus de deux valeurs, mais vous ne pouvez effectuer un filtre de plage que sur la dernière valeur de la propriété composite.
Une variante très spéciale de ceci est implémentée par le bibliothèque GeoFire pour Firebase . Cette bibliothèque combine la latitude et la longitude d'un emplacement dans un soi-disant Geohash , qui peut ensuite être utilisé pour effectuer des requêtes en temps réel sur Firebase.
Une autre alternative consiste à faire ce que nous avons tous fait avant l’ajout de cette nouvelle API de requête: créer un index dans un autre noeud:
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
Il y a probablement plus d'approches. Par exemple, cette réponse met en évidence un autre index personnalisé en forme d’arbre: https://stackoverflow.com/a/3410506
J'ai écrit une bibliothèque personnelle qui vous permet de commander par plusieurs valeurs, avec toutes les commandes effectuées sur le serveur.
Querybase prend en référence une base de données Firebase et un tableau de champs que vous souhaitez indexer. Lorsque vous créez de nouveaux enregistrements, la génération de clés permettant plusieurs requêtes est automatiquement traitée. La mise en garde est qu'il ne prend en charge que l'équivalence directe (pas moins que ou plus grand que).
const databaseRef = firebase.database().ref().child('people');
const querybaseRef = querybase.ref(databaseRef, ['name', 'age', 'location']);
// Automatically handles composite keys
querybaseRef.Push({
name: 'David',
age: 27,
location: 'SF'
});
// Find records by multiple fields
// returns a Firebase Database ref
const queriedDbRef = querybaseRef
.where({
name: 'David',
age: 27
});
// Listen for realtime updates
queriedDbRef.on('value', snap => console.log(snap));
var ref = new Firebase('https://your.firebaseio.com/');
Query query = ref.orderByChild('genre').equalTo('comedy');
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot movieSnapshot : dataSnapshot.getChildren()) {
Movie movie = dataSnapshot.getValue(Movie.class);
if (movie.getLead().equals('Jack Nicholson')) {
console.log(movieSnapshot.getKey());
}
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
ref.orderByChild("lead").startAt("Jack Nicholson").endAt("Jack Nicholson").listner....
Cela fonctionnera.