Interroger et filtrer les données
Firestore propose une fonctionnalité de requête puissante qui vous permet de spécifier les documents que vous souhaitez récupérer dans une collection ou un groupe de collections. Ces requêtes peuvent également être utilisées avec get()
ou addSnapshotListener()
, comme décrit dans les sections Obtenir des données et Obtenir des mises à jour en temps réel.
Exemple de données
Pour commencer, écrivez des données sur les villes afin de pouvoir étudier différentes façons de les relire :
import { collection, doc, setDoc } from "firebase/firestore"; const citiesRef = collection(db, "cities"); await setDoc(doc(citiesRef, "SF"), { name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860000, regions: ["west_coast", "norcal"] }); await setDoc(doc(citiesRef, "LA"), { name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3900000, regions: ["west_coast", "socal"] }); await setDoc(doc(citiesRef, "DC"), { name: "Washington, D.C.", state: null, country: "USA", capital: true, population: 680000, regions: ["east_coast"] }); await setDoc(doc(citiesRef, "TOK"), { name: "Tokyo", state: null, country: "Japan", capital: true, population: 9000000, regions: ["kanto", "honshu"] }); await setDoc(doc(citiesRef, "BJ"), { name: "Beijing", state: null, country: "China", capital: true, population: 21500000, regions: ["jingjinji", "hebei"] });
var citiesRef = db.collection("cities"); citiesRef.doc("SF").set({ name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860000, regions: ["west_coast", "norcal"] }); citiesRef.doc("LA").set({ name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3900000, regions: ["west_coast", "socal"] }); citiesRef.doc("DC").set({ name: "Washington, D.C.", state: null, country: "USA", capital: true, population: 680000, regions: ["east_coast"] }); citiesRef.doc("TOK").set({ name: "Tokyo", state: null, country: "Japan", capital: true, population: 9000000, regions: ["kanto", "honshu"] }); citiesRef.doc("BJ").set({ name: "Beijing", state: null, country: "China", capital: true, population: 21500000, regions: ["jingjinji", "hebei"] });
let citiesRef = db.collection("cities") citiesRef.document("SF").setData([ "name": "San Francisco", "state": "CA", "country": "USA", "capital": false, "population": 860000, "regions": ["west_coast", "norcal"] ]) citiesRef.document("LA").setData([ "name": "Los Angeles", "state": "CA", "country": "USA", "capital": false, "population": 3900000, "regions": ["west_coast", "socal"] ]) citiesRef.document("DC").setData([ "name": "Washington D.C.", "country": "USA", "capital": true, "population": 680000, "regions": ["east_coast"] ]) citiesRef.document("TOK").setData([ "name": "Tokyo", "country": "Japan", "capital": true, "population": 9000000, "regions": ["kanto", "honshu"] ]) citiesRef.document("BJ").setData([ "name": "Beijing", "country": "China", "capital": true, "population": 21500000, "regions": ["jingjinji", "hebei"] ])
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [[citiesRef documentWithPath:@"SF"] setData:@{ @"name": @"San Francisco", @"state": @"CA", @"country": @"USA", @"capital": @(NO), @"population": @860000, @"regions": @[@"west_coast", @"norcal"] }]; [[citiesRef documentWithPath:@"LA"] setData:@{ @"name": @"Los Angeles", @"state": @"CA", @"country": @"USA", @"capital": @(NO), @"population": @3900000, @"regions": @[@"west_coast", @"socal"] }]; [[citiesRef documentWithPath:@"DC"] setData:@{ @"name": @"Washington D.C.", @"country": @"USA", @"capital": @(YES), @"population": @680000, @"regions": @[@"east_coast"] }]; [[citiesRef documentWithPath:@"TOK"] setData:@{ @"name": @"Tokyo", @"country": @"Japan", @"capital": @(YES), @"population": @9000000, @"regions": @[@"kanto", @"honshu"] }]; [[citiesRef documentWithPath:@"BJ"] setData:@{ @"name": @"Beijing", @"country": @"China", @"capital": @(YES), @"population": @21500000, @"regions": @[@"jingjinji", @"hebei"] }];
val cities = db.collection("cities") val data1 = hashMapOf( "name" to "San Francisco", "state" to "CA", "country" to "USA", "capital" to false, "population" to 860000, "regions" to listOf("west_coast", "norcal"), ) cities.document("SF").set(data1) val data2 = hashMapOf( "name" to "Los Angeles", "state" to "CA", "country" to "USA", "capital" to false, "population" to 3900000, "regions" to listOf("west_coast", "socal"), ) cities.document("LA").set(data2) val data3 = hashMapOf( "name" to "Washington D.C.", "state" to null, "country" to "USA", "capital" to true, "population" to 680000, "regions" to listOf("east_coast"), ) cities.document("DC").set(data3) val data4 = hashMapOf( "name" to "Tokyo", "state" to null, "country" to "Japan", "capital" to true, "population" to 9000000, "regions" to listOf("kanto", "honshu"), ) cities.document("TOK").set(data4) val data5 = hashMapOf( "name" to "Beijing", "state" to null, "country" to "China", "capital" to true, "population" to 21500000, "regions" to listOf("jingjinji", "hebei"), ) cities.document("BJ").set(data5)
CollectionReference cities = db.collection("cities"); Map<String, Object> data1 = new HashMap<>(); data1.put("name", "San Francisco"); data1.put("state", "CA"); data1.put("country", "USA"); data1.put("capital", false); data1.put("population", 860000); data1.put("regions", Arrays.asList("west_coast", "norcal")); cities.document("SF").set(data1); Map<String, Object> data2 = new HashMap<>(); data2.put("name", "Los Angeles"); data2.put("state", "CA"); data2.put("country", "USA"); data2.put("capital", false); data2.put("population", 3900000); data2.put("regions", Arrays.asList("west_coast", "socal")); cities.document("LA").set(data2); Map<String, Object> data3 = new HashMap<>(); data3.put("name", "Washington D.C."); data3.put("state", null); data3.put("country", "USA"); data3.put("capital", true); data3.put("population", 680000); data3.put("regions", Arrays.asList("east_coast")); cities.document("DC").set(data3); Map<String, Object> data4 = new HashMap<>(); data4.put("name", "Tokyo"); data4.put("state", null); data4.put("country", "Japan"); data4.put("capital", true); data4.put("population", 9000000); data4.put("regions", Arrays.asList("kanto", "honshu")); cities.document("TOK").set(data4); Map<String, Object> data5 = new HashMap<>(); data5.put("name", "Beijing"); data5.put("state", null); data5.put("country", "China"); data5.put("capital", true); data5.put("population", 21500000); data5.put("regions", Arrays.asList("jingjinji", "hebei")); cities.document("BJ").set(data5);
final cities = db.collection("cities"); final data1 = <String, dynamic>{ "name": "San Francisco", "state": "CA", "country": "USA", "capital": false, "population": 860000, "regions": ["west_coast", "norcal"] }; cities.doc("SF").set(data1); final data2 = <String, dynamic>{ "name": "Los Angeles", "state": "CA", "country": "USA", "capital": false, "population": 3900000, "regions": ["west_coast", "socal"], }; cities.doc("LA").set(data2); final data3 = <String, dynamic>{ "name": "Washington D.C.", "state": null, "country": "USA", "capital": true, "population": 680000, "regions": ["east_coast"] }; cities.doc("DC").set(data3); final data4 = <String, dynamic>{ "name": "Tokyo", "state": null, "country": "Japan", "capital": true, "population": 9000000, "regions": ["kanto", "honshu"] }; cities.doc("TOK").set(data4); final data5 = <String, dynamic>{ "name": "Beijing", "state": null, "country": "China", "capital": true, "population": 21500000, "regions": ["jingjinji", "hebei"], }; cities.doc("BJ").set(data5);
class City: def __init__(self, name, state, country, capital=False, population=0, regions=[]): self.name = name self.state = state self.country = country self.capital = capital self.population = population self.regions = regions @staticmethod def from_dict(source): # ... def to_dict(self): # ... def __repr__(self): return f"City(\ name={self.name}, \ country={self.country}, \ population={self.population}, \ capital={self.capital}, \ regions={self.regions}\ )"
cities_ref = db.collection("cities") cities_ref.document("BJ").set( City("Beijing", None, "China", True, 21500000, ["hebei"]).to_dict() ) cities_ref.document("SF").set( City( "San Francisco", "CA", "USA", False, 860000, ["west_coast", "norcal"] ).to_dict() ) cities_ref.document("LA").set( City( "Los Angeles", "CA", "USA", False, 3900000, ["west_coast", "socal"] ).to_dict() ) cities_ref.document("DC").set( City("Washington D.C.", None, "USA", True, 680000, ["east_coast"]).to_dict() ) cities_ref.document("TOK").set( City("Tokyo", None, "Japan", True, 9000000, ["kanto", "honshu"]).to_dict() )
class City: def __init__(self, name, state, country, capital=False, population=0, regions=[]): self.name = name self.state = state self.country = country self.capital = capital self.population = population self.regions = regions @staticmethod def from_dict(source): # ... def to_dict(self): # ... def __repr__(self): return f"City(\ name={self.name}, \ country={self.country}, \ population={self.population}, \ capital={self.capital}, \ regions={self.regions}\ )"
cities_ref = db.collection("cities") await cities_ref.document("BJ").set( City("Beijing", None, "China", True, 21500000, ["hebei"]).to_dict() ) await cities_ref.document("SF").set( City( "San Francisco", "CA", "USA", False, 860000, ["west_coast", "norcal"] ).to_dict() ) await cities_ref.document("LA").set( City( "Los Angeles", "CA", "USA", False, 3900000, ["west_coast", "socal"] ).to_dict() ) await cities_ref.document("DC").set( City("Washington D.C.", None, "USA", True, 680000, ["east_coast"]).to_dict() ) await cities_ref.document("TOK").set( City("Tokyo", None, "Japan", True, 9000000, ["kanto", "honshu"]).to_dict() )
CollectionReference cities = db->Collection("cities"); cities.Document("SF").Set({ {"name", FieldValue::String("San Francisco")}, {"state", FieldValue::String("CA")}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(false)}, {"population", FieldValue::Integer(860000)}, {"regions", FieldValue::Array({FieldValue::String("west_coast"), FieldValue::String("norcal")})}, }); cities.Document("LA").Set({ {"name", FieldValue::String("Los Angeles")}, {"state", FieldValue::String("CA")}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(false)}, {"population", FieldValue::Integer(3900000)}, {"regions", FieldValue::Array({FieldValue::String("west_coast"), FieldValue::String("socal")})}, }); cities.Document("DC").Set({ {"name", FieldValue::String("Washington D.C.")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(680000)}, {"regions", FieldValue::Array({FieldValue::String("east_coast")})}, }); cities.Document("TOK").Set({ {"name", FieldValue::String("Tokyo")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("Japan")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(9000000)}, {"regions", FieldValue::Array({FieldValue::String("kanto"), FieldValue::String("honshu")})}, }); cities.Document("BJ").Set({ {"name", FieldValue::String("Beijing")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("China")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(21500000)}, {"regions", FieldValue::Array({FieldValue::String("jingjinji"), FieldValue::String("hebei")})}, });
CollectionReference citiesRef = db.Collection("cities"); citiesRef.Document("SF").SetAsync(new Dictionary<string, object>(){ { "Name", "San Francisco" }, { "State", "CA" }, { "Country", "USA" }, { "Capital", false }, { "Population", 860000 }, { "Regions", new ArrayList{"west_coast", "norcal"} } }); citiesRef.Document("LA").SetAsync(new Dictionary<string, object>(){ { "Name", "Los Angeles" }, { "State", "CA" }, { "Country", "USA" }, { "Capital", false }, { "Population", 3900000 }, { "Regions", new ArrayList{"west_coast", "socal"} } }); citiesRef.Document("DC").SetAsync(new Dictionary<string, object>(){ { "Name", "Washington D.C." }, { "State", null }, { "Country", "USA" }, { "Capital", true }, { "Population", 680000 }, { "Regions", new ArrayList{"east_coast"} } }); citiesRef.Document("TOK").SetAsync(new Dictionary<string, object>(){ { "Name", "Tokyo" }, { "State", null }, { "Country", "Japan" }, { "Capital", true }, { "Population", 9000000 }, { "Regions", new ArrayList{"kanto", "honshu"} } }); citiesRef.Document("BJ").SetAsync(new Dictionary<string, object>(){ { "Name", "Beijing" }, { "State", null }, { "Country", "China" }, { "Capital", true }, { "Population", 21500000 }, { "Regions", new ArrayList{"jingjinji", "hebei"} } });
Requêtes simples
La requête suivante renvoie toutes les villes avec l'état CA
:
// Create a reference to the cities collection import { collection, query, where } from "firebase/firestore"; const citiesRef = collection(db, "cities"); // Create a query against the collection. const q = query(citiesRef, where("state", "==", "CA"));
// Create a reference to the cities collection var citiesRef = db.collection("cities"); // Create a query against the collection. var query = citiesRef.where("state", "==", "CA");
// Create a reference to the cities collection let citiesRef = db.collection("cities") // Create a query against the collection. let query = citiesRef.whereField("state", isEqualTo: "CA")
// Create a reference to the cities collection FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; // Create a query against the collection. FIRQuery *query = [citiesRef queryWhereField:@"state" isEqualTo:@"CA"];
// Create a reference to the cities collection val citiesRef = db.collection("cities") // Create a query against the collection. val query = citiesRef.whereEqualTo("state", "CA")
// Create a reference to the cities collection CollectionReference citiesRef = db.collection("cities"); // Create a query against the collection. Query query = citiesRef.whereEqualTo("state", "CA");
// Create a reference to the cities collection final citiesRef = db.collection("cities"); // Create a query against the collection. final query = citiesRef.where("state", isEqualTo: "CA");
CollectionReference cities_ref = db->Collection("cities"); // Create a query against the collection. Query query_ca = cities_ref.WhereEqualTo("state", FieldValue::String("CA"));
CollectionReference citiesRef = db.Collection("cities"); Query query = citiesRef.WhereEqualTo("State", "CA"); query.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask) => { foreach (DocumentSnapshot documentSnapshot in querySnapshotTask.Result.Documents) { Debug.Log(String.Format("Document {0} returned by query State=CA", documentSnapshot.Id)); } });
La requête suivante renvoie toutes les capitales :
import { collection, query, where } from "firebase/firestore"; const citiesRef = collection(db, "cities"); const q = query(citiesRef, where("capital", "==", true));
var citiesRef = db.collection("cities"); var query = citiesRef.where("capital", "==", true);
let capitalCities = db.collection("cities").whereField("capital", isEqualTo: true)
FIRQuery *capitalCities = [[self.db collectionWithPath:@"cities"] queryWhereField:@"capital" isEqualTo:@YES];
val capitalCities = db.collection("cities").whereEqualTo("capital", true)
Query capitalCities = db.collection("cities").whereEqualTo("capital", true);
final capitalcities = db.collection("cities").where("capital", isEqualTo: true);
Query capital_cities = db->Collection("cities").WhereEqualTo( "capital", FieldValue::Boolean(true));
CollectionReference citiesRef = db.Collection("cities"); Query query = citiesRef.WhereEqualTo("Capital", true); query.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask) => { foreach (DocumentSnapshot documentSnapshot in querySnapshotTask.Result.Documents) { Debug.Log(String.Format("Document {0} returned by query Capital=true", documentSnapshot.Id)); } });
Exécuter une requête
Après avoir créé un objet de requête, utilisez la fonction get()
pour extraire les résultats :
import { collection, query, where, getDocs } from "firebase/firestore"; const q = query(collection(db, "cities"), where("capital", "==", true)); const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); });
db.collection("cities").where("capital", "==", true) .get() .then((querySnapshot) => { querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); }); }) .catch((error) => { console.log("Error getting documents: ", error); });
do { let querySnapshot = try await db.collection("cities").whereField("capital", isEqualTo: true) .getDocuments() for document in querySnapshot.documents { print("\(document.documentID) => \(document.data())") } } catch { print("Error getting documents: \(error)") }
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"capital" isEqualTo:@(YES)] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error getting documents: %@", error); } else { for (FIRDocumentSnapshot *document in snapshot.documents) { NSLog(@"%@ => %@", document.documentID, document.data); } } }];
db.collection("cities") .whereEqualTo("capital", true) .get() .addOnSuccessListener { documents -> for (document in documents) { Log.d(TAG, "${document.id} => ${document.data}") } } .addOnFailureListener { exception -> Log.w(TAG, "Error getting documents: ", exception) }
db.collection("cities") .whereEqualTo("capital", true) .get() .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { Log.d(TAG, document.getId() + " => " + document.getData()); } } else { Log.d(TAG, "Error getting documents: ", task.getException()); } } });
db.collection("cities").where("capital", isEqualTo: true).get().then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { print('${docSnapshot.id} => ${docSnapshot.data()}'); } }, onError: (e) => print("Error completing: $e"), );
db->Collection("cities") .WhereEqualTo("capital", FieldValue::Boolean(true)) .Get() .OnCompletion([](const Future<QuerySnapshot>& future) { if (future.error() == Error::kErrorOk) { for (const DocumentSnapshot& document : future.result()->documents()) { std::cout << document << std::endl; } } else { std::cout << "Error getting documents: " << future.error_message() << std::endl; } });
PHP
Pour vous authentifier auprès de Firestore, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.
Query capitalQuery = db.Collection("cities").WhereEqualTo("Capital", true); capitalQuery.GetSnapshotAsync().ContinueWithOnMainThread(task => { QuerySnapshot capitalQuerySnapshot = task.Result; foreach (DocumentSnapshot documentSnapshot in capitalQuerySnapshot.Documents) { Debug.Log(String.Format("Document data for {0} document:", documentSnapshot.Id)); Dictionary<string, object> city = documentSnapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } // Newline to separate entries Debug.Log(""); }; });
Pour en savoir plus sur la récupération des résultats des requêtes, consultez l'article Obtenir des données. Vous pouvez également ajouter un écouteur à une requête pour obtenir les résultats actuels et écouter les futures mises à jour.
Opérateurs de requêtes
La méthode where()
utilise trois paramètres : un champ à filtrer, un opérateur de comparaison et une valeur. Firestore est compatible avec les opérateurs de comparaison suivants :
<
less than (inférieur à)<=
less than or equal to (inférieur ou égal à)==
equal to (égal à)>
greater than (supérieur à)>=
greater than or equal to (supérieur ou égal à)!=
not equal to (non égal à)array-contains
array-contains-any
in
not-in
Exemple :
const stateQuery = query(citiesRef, where("state", "==", "CA")); const populationQuery = query(citiesRef, where("population", "<", 100000)); const nameQuery = query(citiesRef, where("name", ">=", "San Francisco"));
const stateQuery = citiesRef.where("state", "==", "CA"); const populationQuery = citiesRef.where("population", "<", 100000); const nameQuery = citiesRef.where("name", ">=", "San Francisco");
let stateQuery = citiesRef.whereField("state", isEqualTo: "CA") let populationQuery = citiesRef.whereField("population", isLessThan: 100000) let nameQuery = citiesRef.whereField("name", isGreaterThanOrEqualTo: "San Francisco")
FIRQuery *stateQuery = [citiesRef queryWhereField:@"state" isEqualTo:@"CA"]; FIRQuery *populationQuery = [citiesRef queryWhereField:@"population" isLessThan:@100000]; FIRQuery *nameQuery = [citiesRef queryWhereField:@"name" isGreaterThanOrEqualTo:@"San Francisco"];
val stateQuery = citiesRef.whereEqualTo("state", "CA") val populationQuery = citiesRef.whereLessThan("population", 100000) val nameQuery = citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco")
Query stateQuery = citiesRef.whereEqualTo("state", "CA"); Query populationQuery = citiesRef.whereLessThan("population", 100000); Query nameQuery = citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco");
final citiesRef = db.collection("cities"); final stateQuery = citiesRef.where("state", isEqualTo: "CA"); final populationQuery = citiesRef.where("population", isLessThan: 100000); final nameQuery = citiesRef.where("name", isEqualTo: "San Francisco");
cities_ref.WhereEqualTo("state", FieldValue::String("CA")); cities_ref.WhereLessThan("population", FieldValue::Integer(100000)); cities_ref.WhereGreaterThanOrEqualTo("name", FieldValue::String("San Francisco"));
Query stateQuery = citiesRef.WhereEqualTo("State", "CA"); Query populationQuery = citiesRef.WhereGreaterThan("Population", 1000000); Query nameQuery = citiesRef.WhereGreaterThanOrEqualTo("Name", "San Francisco");
Not Equal (!=
)
Utilisez l'opérateur "not equal" (!=
) pour renvoyer des documents dont le champ donné existe et ne correspond pas à la valeur de comparaison. Exemple :
const notCapitalQuery = query(citiesRef, where("capital", "!=", false));
citiesRef.where("capital", "!=", false);
let notEqualQuery = citiesRef.whereField("capital", isNotEqualTo: false)
query = [citiesRef queryWhereField:@"capital" isNotEqualTo:@NO];
val notCapitalQuery = citiesRef.whereNotEqualTo("capital", false)
Query notCapitalQuery = citiesRef.whereNotEqualTo("capital", false);
final citiesRef = db.collection("cities"); final notCapitals = citiesRef.where("capital", isNotEqualTo: true);
// Snippet not yet available
cities_ref.WhereNotEqualTo("capital", FieldValue::Boolean(false));
// Snippet not yet available
Query query = citiesRef.WhereNotEqualTo("capital", false); Query query = citiesRef.WhereNotEqualTo("capital", false);
// Snippet not yet available
Cette requête renvoie chaque document city
où le champ capital
a une valeur autre que false
ou null
. Cela inclut les documents city
dont la valeur du champ capital
est égale à true
ou toute valeur non booléenne autre que null
.
Cette requête ne renvoie pas de documents city
où le champ capital
n'existe pas. Les requêtes Not-equal (!=
) et not-in
excluent les documents lorsque le champ donné n'existe pas.
Un champ existe lorsqu'il est défini sur n'importe quelle valeur, y compris une chaîne vide (""
), null
et NaN
(et non un nombre). Notez que les valeurs du champ null
ne correspondent pas aux clauses !=
, car x != null
renvoie undefined
.
Limites
Veuillez noter les limites suivantes pour les requêtes !=
:
- Seuls les documents dont le champ donné existe peuvent correspondre à la requête.
- Vous ne pouvez pas combiner
not-in
et!=
dans une requête composée.
Adhésion au tableau
Vous pouvez utiliser l'opérateur array-contains
pour effectuer un filtrage en fonction des valeurs de tableau. Exemple :
import { query, where } from "firebase/firestore"; const q = query(citiesRef, where("regions", "array-contains", "west_coast"));
citiesRef.where("regions", "array-contains", "west_coast");
citiesRef .whereField("regions", arrayContains: "west_coast")
[citiesRef queryWhereField:@"state" arrayContains:@"west_coast"];
val citiesRef = db.collection("cities") citiesRef.whereArrayContains("regions", "west_coast")
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContains("regions", "west_coast");
final citiesRef = db.collection("cities"); final westCoastcities = citiesRef.where("regions", arrayContains: "west_coast");
CollectionReference cities_ref = db->Collection("cities"); cities_ref.WhereArrayContains("region", FieldValue::String("west_coast"));
CollectionReference citiesRef = db.Collection("cities"); Query arrayContainsQuery = citiesRef.WhereArrayContains("region", "west_coast");
Cette requête renvoie chaque document city
où le champ regions
est un tableau contenant west_coast
. Si le tableau comporte plusieurs instances de la valeur de la requête, le document n'est inclus qu'une seule fois dans les résultats.
Vous ne pouvez utiliser qu'une seule clause array-contains
par disjonction (groupe or
).
Vous ne pouvez pas combiner array-contains
avec array-contains-any
dans la même disjonction.
in
, not-in
et array-contains-any
Utilisez l'opérateur in
pour combiner jusqu'à 30 clauses d'égalité (==
) dans le même champ avec un opérateur OR
logique. Une requête in
renvoie des documents où le champ indiqué correspond à n'importe quelle valeur de comparaison.
Exemple :
import { query, where } from "firebase/firestore"; const q = query(citiesRef, where('country', 'in', ['USA', 'Japan']));
citiesRef.where('country', 'in', ['USA', 'Japan']);
let citiesRef = db.collection("cities") citiesRef.whereField("country", in: ["USA", "Japan"])
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [citiesRef queryWhereField:@"country" in:@[@"USA", @"Japan"]];
val citiesRef = db.collection("cities") citiesRef.whereIn("country", listOf("USA", "Japan"))
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereIn("country", Arrays.asList("USA", "Japan"));
final citiesRef = db.collection("cities"); final cities = citiesRef.where("country", whereIn: ["USA", "Japan"]);
CollectionReference cities_ref = db->Collection("cities"); cities_ref.WhereIn("country", std::vector<FieldValue> { FieldValue::String("USA"), FieldValue::String("Japan") });
CollectionReference citiesRef = db.Collection("cities"); ListcountriesList = new List<object>() {"USA", "Japan"}; Query whereInQuery = citiesRef.WhereIn("country", countriesList);
Cette requête renvoie chaque document city
où le champ country
est USA
ou Japan
. Dans l'exemple de données, cela inclut les documents SF
, LA
, DC
et TOK
.
not-in
Utilisez l'opérateur not-in
pour combiner jusqu'à 10 clauses non différentes (!=
) sur le même champ avec un opérateur AND
logique. Une requête not-in
renvoie des documents où le champ donné existe, mais n'est pas null
et ne correspond à aucune des valeurs de comparaison. Exemple :
import { query, where } from "firebase/firestore"; const q = query(citiesRef, where('country', 'not-in', ['USA', 'Japan']));
citiesRef.where('country', 'not-in', ['USA', 'Japan']);
citiesRef.whereField("country", notIn: ["USA", "Japan"])
[citiesRef queryWhereField:@"country" notIn:@[@"USA", @"Japan"]];
citiesRef.whereNotIn("country", listOf("USA", "Japan"))
citiesRef.whereNotIn("country", Arrays.asList("USA", "Japan"));
final citiesRef = db.collection("cities"); final cities = citiesRef.where("country", whereNotIn: ["USA", "Japan"]);
// Snippet not yet available
cities_ref.WhereNotIn("country", std::vector<FieldValue> { FieldValue::String("USA"), FieldValue::String("Japan") });
// Snippet not yet available
Query query = citiesRef.WhereNotIn(new FieldPath("country"), new List<string>{"USA", "Japan"}); Query query = citiesRef.WhereNotIn("country", new List<object>(){"USA", "Japan"});
// Snippet not yet available
Cette requête renvoie chaque document city
où le champ country
existe et n'est pas défini sur USA
, Japan
ou null
. Dans l'exemple de données, cela inclut les documents London
et Hong Kong
.
Les requêtes not-in
excluent les documents pour lesquels le champ donné n'existe pas. Un champ existe lorsqu'il est défini sur n'importe quelle valeur, y compris une chaîne vide (""
), null
et NaN
(et non un nombre). Notez que x != null
renvoie undefined
. Une requête not-in
avec null
comme l'une des valeurs de comparaison ne correspond à aucun document.
array-contains-any
Utilisez l'opérateur array-contains-any
pour combiner jusqu'à 30 clauses array-contains
sur le même champ avec un OR
logique. Une requête array-contains-any
renvoie des documents où le champ indiqué est un tableau contenant une ou plusieurs des valeurs de comparaison:
import { query, where } from "firebase/firestore"; const q = query(citiesRef, where('regions', 'array-contains-any', ['west_coast', 'east_coast']));
citiesRef.where('regions', 'array-contains-any', ['west_coast', 'east_coast']);
let citiesRef = db.collection("cities") citiesRef.whereField("regions", arrayContainsAny: ["west_coast", "east_coast"])
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [citiesRef queryWhereField:@"regions" arrayContainsAny:@[@"west_coast", @"east_coast"]];
val citiesRef = db.collection("cities") citiesRef.whereArrayContainsAny("regions", listOf("west_coast", "east_coast"))
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContainsAny("regions", Arrays.asList("west_coast", "east_coast"));
final citiesRef = db.collection("cities"); final cities = citiesRef .where("regions", arrayContainsAny: ["west_coast", "east_coast"]);
CollectionReference cities_ref = db->Collection("cities"); cities_ref.WhereArrayContainsAny("region", std::vector<FieldValue> { FieldValue::String("west_coast"), FieldValue::String("east_coast") });
Query query = citiesRef.WhereArrayContainsAny( "regions", new List<object>() { new List<object>(){"west_coast"}, new List<object>(){"east_coast"}});
Cette requête renvoie chaque document de ville où le champ regions
est un tableau contenant west_coast
ou east_coast
. Dans l'exemple de données, cela inclut les documents SF
, LA
et DC
.
Les doublons provenant de array-contains-any
sont retirés de la liste de résultats. Même si le champ tableau d'un document correspond à plusieurs valeurs de comparaison, ce document n'apparaît qu'une seule fois dans les résultats.
array-contains-any
filtre toujours le type de données du tableau. Par exemple, la requête ci-dessus ne renverrait pas un document de ville dans lequel, au lieu d'un tableau, le champ regions
est la chaîne west_coast
.
Vous pouvez utiliser une valeur de tableau comme valeur de comparaison pour in
, mais contrairement à array-contains-any
, la clause recherche une correspondance exacte de longueur, de classement et de valeurs dans le tableau. Exemple :
import { query, where } from "firebase/firestore"; const q = query(citiesRef, where('regions', 'in', [['west_coast'], ['east_coast']]));
citiesRef.where('regions', 'in', [['west_coast'], ['east_coast']]);
citiesRef.whereField("regions", in: [["west_coast"], ["east_coast"]])
[citiesRef queryWhereField:@"regions" in:@[@[@"west_coast"], @[@"east_coast"]]];
citiesRef.whereIn("regions", listOf(arrayOf("west_coast"), arrayOf("east_coast")))
citiesRef.whereIn("regions", Arrays.asList(new String[]{"west_coast"}, new String[]{"east_coast"}));
final citiesRef = db.collection("cities"); final cities = citiesRef.where("regions", whereIn: [ ["west_coast"], ["east_coast"] ]);
cities_ref.WhereIn("region", std::vector<FieldValue> { FieldValue::String("west_coast"), FieldValue::String("east_coast") });
Query query = citiesRef.WhereIn(new FieldPath("regions"), new List<string>{"west_coast", "east_coast"});
Cette requête renvoie chaque document de ville où le champ regions
est un tableau contenant exactement un élément de west_coast
ou de east_coast
.
Dans l'exemple de données, seul le document DC
est concerné avec son champ regions
de valeur ["east_coast"]
. Le document SF
, en revanche, ne correspond pas, car son champ regions
est ["west_coast", "norcal"]
.
Limites
Veuillez noter les limites suivantes pour in
, not-in
et array-contains-any
:
- Firestore est compatible avec les requêtes
OR
logiques via les opérateursor
,in
etarray-contains-any
. Ces requêtes sont limitées à 30 disjonctions en fonction de la forme normale disjonctive de la requête. - Vous ne pouvez utiliser qu'une seule clause
array-contains
par disjonction (groupeor
). Vous ne pouvez pas combinerarray-contains
avecarray-contains-any
dans la même disjonction. - Vous ne pouvez pas combiner
not-in
avec l'opérateur "différent de"!=
. not-in
accepte jusqu'à 10 valeurs de comparaison.
Requêtes composées (AND
)
Vous pouvez combiner des contraintes avec un AND
logique en enchaînant plusieurs opérateurs d'égalité (==
ou array-contains
). Cependant, vous devez créer un index composite pour combiner les opérateurs d'égalité avec les opérateurs d'inégalité, <
, <=
, >
et !=
.
import { query, where } from "firebase/firestore"; const q1 = query(citiesRef, where("state", "==", "CO"), where("name", "==", "Denver")); const q2 = query(citiesRef, where("state", "==", "CA"), where("population", "<", 1000000));
const q1 = citiesRef.where("state", "==", "CO").where("name", "==", "Denver"); const q2 = citiesRef.where("state", "==", "CA").where("population", "<", 1000000);
citiesRef .whereField("state", isEqualTo: "CO") .whereField("name", isEqualTo: "Denver") citiesRef .whereField("state", isEqualTo: "CA") .whereField("population", isLessThan: 1000000)
[[citiesRef queryWhereField:@"state" isEqualTo:@"CO"] queryWhereField:@"name" isGreaterThanOrEqualTo:@"Denver"]; [[citiesRef queryWhereField:@"state" isEqualTo:@"CA"] queryWhereField:@"population" isLessThan:@1000000];
citiesRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver") citiesRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000)
citiesRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver"); citiesRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000);
final citiesRef = db.collection("cities"); citiesRef .where("state", isEqualTo: "CO") .where("name", isEqualTo: "Denver"); citiesRef .where("state", isEqualTo: "CA") .where("population", isLessThan: 1000000);
cities_ref.WhereEqualTo("state", FieldValue::String("CO")) .WhereEqualTo("name", FieldValue::String("Denver")); cities_ref.WhereEqualTo("state", FieldValue::String("CA")) .WhereLessThan("population", FieldValue::Integer(1000000));
Query chainedQuery = citiesRef .WhereEqualTo("State", "CA") .WhereEqualTo("Name", "San Francisco");
OR
requêtes
Vous pouvez combiner des contraintes avec une OR
logique. Exemple :
const q = query(citiesRef, or(where('capital', '==', true), where('population', '>=', 1000000) ) );
Non disponible.
let query = db.collection("cities").whereFilter(Filter.orFilter([ Filter.whereField("capital", isEqualTo: true), Filter.whereField("population", isGreaterThanOrEqualTo: 1000000); ]))
FIRCollectionReference *collection = [self.db collectionWithPath:@"cities"]; FIRQuery *query = [collection queryWhereFilter:[FIRFilter orFilterWithFilters:@[ [FIRFilter filterWhereField:@"capital" isEqualTo:@YES], [FIRFilter filterWhereField:@"population" isGreaterThanOrEqualTo:@1000000] ]]];
val query = collection.where(Filter.or( Filter.equalTo("capital", true), Filter.greaterThanOrEqualTo("population", 1000000) ))
Query query = collection.where(Filter.or( Filter.equalTo("capital", true), Filter.greaterThanOrEqualTo("population", 1000000) ));
var query = db.collection("cities").where( Filter.or( Filter("capital", isEqualTo: true), Filter("population", isGreaterThan: 1000000), ), );
Extrait non disponible.
Extrait non disponible.
Extrait non disponible.
const bigCities = await citiesRef .where( Filter.or( Filter.where('capital', '==', true), Filter.where('population', '>=', 1000000) ) ) .get();
Extrait non disponible.
Query query = citiesRef.Where(Filter.Or( Filter.EqualTo("State", "CA"), Filter.GreaterThanOrEqualTo("population", 1000000) )); query.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask) => { foreach (DocumentSnapshot documentSnapshot in querySnapshotTask.Result.Documents) { Debug.Log(String.Format("Document {0} returned by query State=CA or population >= {1}", documentSnapshot.Id, 1000000)); } });
Extrait non disponible.
Extrait non disponible.
Firestore utilise vos index composites pour répondre aux requêtes OR
. Si vos index ne sont pas compatibles avec la requête, Firestore suggère des index supplémentaires pour votre base de données.
Vous pouvez combiner des requêtes OR
avec des requêtes composées pour filtrer sur des combinaisons d'opérations OR
et AND
. Exemple :
const q = query(collection(db, "cities"), and( where('state', '==', 'CA'), or( where('capital', '==', true), where('population', '>=', 1000000) ) ));
Non disponible.
let query = db.collection("cities").whereFilter(Filter.andFilter([ Filter.whereField("state", isEqualTo: "CA"), Filter.orFilter([ Filter.whereField("capital", isEqualTo: true), Filter.whereField("population", isGreaterThanOrEqualTo: 1000000) ]) ]))
FIRCollectionReference *collection = [self.db collectionWithPath:@"cities"]; FIRQuery *query = [collection queryWhereFilter:[FIRFilter andFilterWithFilters:@[ [FIRFilter filterWhereField:@"state" isEqualTo:@"CA"], [FIRFilter orFilterWithFilters:@[ [FIRFilter filterWhereField:@"capital" isEqualTo:@YES], [FIRFilter filterWhereField:@"population" isGreaterThanOrEqualTo:@1000000] ]] ]]];
val query = collection.where(Filter.and( Filter.equalTo("state", "CA"), Filter.or( Filter.equalTo("capital", true), Filter.greaterThanOrEqualTo("population", 1000000) ) ))
Query query = collection.where(Filter.and( Filter.equalTo("state", "CA"), Filter.or( Filter.equalTo("capital", true), Filter.greaterThanOrEqualTo("population", 1000000) ) ));
var query = db.collection("cities").where( Filter.and( Filter("state", isEqualTo: "CA"), Filter.or( Filter("capital", isEqualTo: true), Filter("population", isGreaterThan: 1000000), ), ), );
Extrait non disponible.
Extrait non disponible.
Extrait non disponible.
Extrait non disponible.
const bigCitiesInCalifornia = await citiesRef .where('state', '==', 'CA') .where( Filter.or( Filter.where('capital', '==', true), Filter.where('population', '>=', 1000000) ) ) .get();
Extrait non disponible.
Extrait non disponible.
Query query = citiesRef.Where(Filter.And( Filter.EqualTo("state", "CA"), Filter.Or( Filter.EqualTo("capital", true), Filter.GreaterThanOrEqualTo("population", 1000000) ) ));
Extrait non disponible.
Extrait non disponible.
Limites
Veuillez noter les limites suivantes pour les requêtes or
:
- Firestore limite une requête à 30 disjonctions maximum en fonction de sa forme normale disjonctive.
Vous êtes plus susceptible d'atteindre cette limite lorsque vous effectuez une
AND
de plusieurs groupesOR
. - Vous ne pouvez pas combiner
not-in
avecin
,array-contains-any
ouor
dans la même requête.
Pour obtenir une description complète des limites, consultez la section Limites des requêtes.
Requêtes de groupe de collections
Un groupe de collections est constitué de toutes les collections ayant le même ID. Par défaut, les requêtes récupèrent les résultats d'une seule collection de votre base de données. Utilisez une requête de groupe de collections pour extraire des documents d'un groupe de collections plutôt que d'une seule collection.
Par exemple, vous pouvez créer un groupe de collections landmarks
en ajoutant un sous-ensemble de points de repère à chaque ville :
import { collection, addDoc } from "firebase/firestore"; const citiesRef = collection(db, 'cities'); await Promise.all([ addDoc(collection(citiesRef, 'SF', 'landmarks'), { name: 'Golden Gate Bridge', type: 'bridge' }), addDoc(collection(citiesRef, 'SF', 'landmarks'), { name: 'Legion of Honor', type: 'museum' }), addDoc(collection(citiesRef, 'LA', 'landmarks'), { name: 'Griffith Park', type: 'park' }), addDoc(collection(citiesRef, 'LA', 'landmarks'), { name: 'The Getty', type: 'museum' }), addDoc(collection(citiesRef, 'DC', 'landmarks'), { name: 'Lincoln Memorial', type: 'memorial' }), addDoc(collection(citiesRef, 'DC', 'landmarks'), { name: 'National Air and Space Museum', type: 'museum' }), addDoc(collection(citiesRef, 'TOK', 'landmarks'), { name: 'Ueno Park', type: 'park' }), addDoc(collection(citiesRef, 'TOK', 'landmarks'), { name: 'National Museum of Nature and Science', type: 'museum' }), addDoc(collection(citiesRef, 'BJ', 'landmarks'), { name: 'Jingshan Park', type: 'park' }), addDoc(collection(citiesRef, 'BJ', 'landmarks'), { name: 'Beijing Ancient Observatory', type: 'museum' }) ]);
var citiesRef = db.collection('cities'); var landmarks = Promise.all([ citiesRef.doc('SF').collection('landmarks').doc().set({ name: 'Golden Gate Bridge', type: 'bridge' }), citiesRef.doc('SF').collection('landmarks').doc().set({ name: 'Legion of Honor', type: 'museum' }), citiesRef.doc('LA').collection('landmarks').doc().set({ name: 'Griffith Park', type: 'park' }), citiesRef.doc('LA').collection('landmarks').doc().set({ name: 'The Getty', type: 'museum' }), citiesRef.doc('DC').collection('landmarks').doc().set({ name: 'Lincoln Memorial', type: 'memorial' }), citiesRef.doc('DC').collection('landmarks').doc().set({ name: 'National Air and Space Museum', type: 'museum' }), citiesRef.doc('TOK').collection('landmarks').doc().set({ name: 'Ueno Park', type: 'park' }), citiesRef.doc('TOK').collection('landmarks').doc().set({ name: 'National Museum of Nature and Science', type: 'museum' }), citiesRef.doc('BJ').collection('landmarks').doc().set({ name: 'Jingshan Park', type: 'park' }), citiesRef.doc('BJ').collection('landmarks').doc().set({ name: 'Beijing Ancient Observatory', type: 'museum' }) ]);
let citiesRef = db.collection("cities") var data = ["name": "Golden Gate Bridge", "type": "bridge"] citiesRef.document("SF").collection("landmarks").addDocument(data: data) data = ["name": "Legion of Honor", "type": "museum"] citiesRef.document("SF").collection("landmarks").addDocument(data: data) data = ["name": "Griffith Park", "type": "park"] citiesRef.document("LA").collection("landmarks").addDocument(data: data) data = ["name": "The Getty", "type": "museum"] citiesRef.document("LA").collection("landmarks").addDocument(data: data) data = ["name": "Lincoln Memorial", "type": "memorial"] citiesRef.document("DC").collection("landmarks").addDocument(data: data) data = ["name": "National Air and Space Museum", "type": "museum"] citiesRef.document("DC").collection("landmarks").addDocument(data: data) data = ["name": "Ueno Park", "type": "park"] citiesRef.document("TOK").collection("landmarks").addDocument(data: data) data = ["name": "National Museum of Nature and Science", "type": "museum"] citiesRef.document("TOK").collection("landmarks").addDocument(data: data) data = ["name": "Jingshan Park", "type": "park"] citiesRef.document("BJ").collection("landmarks").addDocument(data: data) data = ["name": "Beijing Ancient Observatory", "type": "museum"] citiesRef.document("BJ").collection("landmarks").addDocument(data: data)
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; NSDictionary *data = @{@"name": @"Golden Gate Bridge", @"type": @"bridge"}; [[[citiesRef documentWithPath:@"SF"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Legion of Honor", @"type": @"museum"}; [[[citiesRef documentWithPath:@"SF"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Griffith Park", @"type": @"park"}; [[[citiesRef documentWithPath:@"LA"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"The Getty", @"type": @"museum"}; [[[citiesRef documentWithPath:@"LA"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Lincoln Memorial", @"type": @"memorial"}; [[[citiesRef documentWithPath:@"DC"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"National Air and Space Museum", @"type": @"museum"}; [[[citiesRef documentWithPath:@"DC"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Ueno Park", @"type": @"park"}; [[[citiesRef documentWithPath:@"TOK"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"National Museum of Nature and Science", @"type": @"museum"}; [[[citiesRef documentWithPath:@"TOK"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Jingshan Park", @"type": @"park"}; [[[citiesRef documentWithPath:@"BJ"] collectionWithPath:@"landmarks"] addDocumentWithData:data]; data = @{@"name": @"Beijing Ancient Observatory", @"type": @"museum"}; [[[citiesRef documentWithPath:@"BJ"] collectionWithPath:@"landmarks"] addDocumentWithData:data];
val citiesRef = db.collection("cities") val ggbData = mapOf( "name" to "Golden Gate Bridge", "type" to "bridge", ) citiesRef.document("SF").collection("landmarks").add(ggbData) val lohData = mapOf( "name" to "Legion of Honor", "type" to "museum", ) citiesRef.document("SF").collection("landmarks").add(lohData) val gpData = mapOf( "name" to "Griffth Park", "type" to "park", ) citiesRef.document("LA").collection("landmarks").add(gpData) val tgData = mapOf( "name" to "The Getty", "type" to "museum", ) citiesRef.document("LA").collection("landmarks").add(tgData) val lmData = mapOf( "name" to "Lincoln Memorial", "type" to "memorial", ) citiesRef.document("DC").collection("landmarks").add(lmData) val nasaData = mapOf( "name" to "National Air and Space Museum", "type" to "museum", ) citiesRef.document("DC").collection("landmarks").add(nasaData) val upData = mapOf( "name" to "Ueno Park", "type" to "park", ) citiesRef.document("TOK").collection("landmarks").add(upData) val nmData = mapOf( "name" to "National Musuem of Nature and Science", "type" to "museum", ) citiesRef.document("TOK").collection("landmarks").add(nmData) val jpData = mapOf( "name" to "Jingshan Park", "type" to "park", ) citiesRef.document("BJ").collection("landmarks").add(jpData) val baoData = mapOf( "name" to "Beijing Ancient Observatory", "type" to "musuem", ) citiesRef.document("BJ").collection("landmarks").add(baoData)
CollectionReference citiesRef = db.collection("cities"); Map<String, Object> ggbData = new HashMap<>(); ggbData.put("name", "Golden Gate Bridge"); ggbData.put("type", "bridge"); citiesRef.document("SF").collection("landmarks").add(ggbData); Map<String, Object> lohData = new HashMap<>(); lohData.put("name", "Legion of Honor"); lohData.put("type", "museum"); citiesRef.document("SF").collection("landmarks").add(lohData); Map<String, Object> gpData = new HashMap<>(); gpData.put("name", "Griffith Park"); gpData.put("type", "park"); citiesRef.document("LA").collection("landmarks").add(gpData); Map<String, Object> tgData = new HashMap<>(); tgData.put("name", "The Getty"); tgData.put("type", "museum"); citiesRef.document("LA").collection("landmarks").add(tgData); Map<String, Object> lmData = new HashMap<>(); lmData.put("name", "Lincoln Memorial"); lmData.put("type", "memorial"); citiesRef.document("DC").collection("landmarks").add(lmData); Map<String, Object> nasaData = new HashMap<>(); nasaData.put("name", "National Air and Space Museum"); nasaData.put("type", "museum"); citiesRef.document("DC").collection("landmarks").add(nasaData); Map<String, Object> upData = new HashMap<>(); upData.put("name", "Ueno Park"); upData.put("type", "park"); citiesRef.document("TOK").collection("landmarks").add(upData); Map<String, Object> nmData = new HashMap<>(); nmData.put("name", "National Museum of Nature and Science"); nmData.put("type", "museum"); citiesRef.document("TOK").collection("landmarks").add(nmData); Map<String, Object> jpData = new HashMap<>(); jpData.put("name", "Jingshan Park"); jpData.put("type", "park"); citiesRef.document("BJ").collection("landmarks").add(jpData); Map<String, Object> baoData = new HashMap<>(); baoData.put("name", "Beijing Ancient Observatory"); baoData.put("type", "museum"); citiesRef.document("BJ").collection("landmarks").add(baoData);
final citiesRef = db.collection("cities"); final ggbData = {"name": "Golden Gate Bridge", "type": "bridge"}; citiesRef.doc("SF").collection("landmarks").add(ggbData); final lohData = {"name": "Legion of Honor", "type": "museum"}; citiesRef.doc("SF").collection("landmarks").add(lohData); final gpData = {"name": "Griffth Park", "type": "park"}; citiesRef.doc("LA").collection("landmarks").add(gpData); final tgData = {"name": "The Getty", "type": "museum"}; citiesRef.doc("LA").collection("landmarks").add(tgData); final lmData = {"name": "Lincoln Memorial", "type": "memorial"}; citiesRef.doc("DC").collection("landmarks").add(lmData); final nasaData = { "name": "National Air and Space Museum", "type": "museum" }; citiesRef.doc("DC").collection("landmarks").add(nasaData); final upData = {"name": "Ueno Park", "type": "park"}; citiesRef.doc("TOK").collection("landmarks").add(upData); final nmData = { "name": "National Musuem of Nature and Science", "type": "museum" }; citiesRef.doc("TOK").collection("landmarks").add(nmData); final jpData = {"name": "Jingshan Park", "type": "park"}; citiesRef.doc("BJ").collection("landmarks").add(jpData); final baoData = {"name": "Beijing Ancient Observatory", "type": "musuem"}; citiesRef.doc("BJ").collection("landmarks").add(baoData);
// Get a new write batch
WriteBatch batch = db->batch();
DocumentReference sf_ref = db->Collection("cities").Document("SF");
batch.Set(sf_ref,{{"name", FieldValue::String("Golden Gate Bridge")}, {"type", FieldValue::String("bridge")}});
batch.Set(sf_ref,{{"name", FieldValue::String("Legion of Honor")}, {"type", FieldValue::String("museum")}});
DocumentReference la_ref = db->Collection("cities").Document("LA");
batch.Set(la_ref,{{"name", FieldValue::String("Griffith Park")}, {"type", FieldValue::String("park")}});
batch.Set(la_ref,{{"name", FieldValue::String("The Getty")}, {"type", FieldValue::String("museum")}});
DocumentReference dc_ref = db->Collection("cities").Document("DC");
batch.Set(dc_ref,{{"name", FieldValue::String("Lincoln Memorial")}, {"type", FieldValue::String("memorial")}});
batch.Set(dc_ref,{{"name", FieldValue::String("National Air and Space Museum")}, {"type", FieldValue::String("museum")}});
DocumentReference tok_ref = db->Collection("cities").Document("TOK");
batch.Set(tok_ref,{{"name", FieldValue::String("Ueno Park")}, {"type", FieldValue::String("park")}});
batch.Set(tok_ref,{{"name", FieldValue::String("National Museum of Nature and Science")}, {"type", FieldValue::String("museum")}});
DocumentReference bj_ref = db->Collection("cities").Document("BJ");
batch.Set(bj_ref,{{"name", FieldValue::String("Jingshan Park")}, {"type", FieldValue::String("park")}});
batch.Set(bj_ref,{{"name", FieldValue::String("Beijing Ancient Observatory")}, {"type", FieldValue::String("museum")}});
// Commit the batch
batch.Commit().OnCompletion([](const Future<void>& future) {
if (future.error() == Error::kErrorOk) {
std::cout << "Write batch success!" << std::endl;
} else {
std::cout << "Write batch failure: " << future.error_message() << std::endl;
}
});
List<Task<DocumentReference>> futures = new List<Task<DocumentReference>>(){ citiesRef .Document("SF") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Golden Gate Bridge"}, {"type", "bridge"}, } ), citiesRef .Document("SF") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Legion of Honor"}, {"type", "museum"}, } ), citiesRef .Document("LA") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Griffith Park"}, {"type", "park"}, } ), citiesRef .Document("LA") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "The Getty"}, {"type", "museum"}, } ), citiesRef .Document("DC") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Lincoln Memorial"}, {"type", "memorial"}, } ), citiesRef .Document("DC") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "National Air and Space Museum"}, {"type", "museum"}, } ), citiesRef .Document("TOK") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Ueno Park"}, {"type", "park"}, } ), citiesRef .Document("TOK") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "National Museum of Nature and Science"}, {"type", "museum"}, } ), citiesRef .Document("BJ") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Jingshan Park"}, {"type", "park"}, } ), citiesRef .Document("BJ") .Collection("landmarks") .AddAsync( new Dictionary<string, object>() { {"name", "Beijing Ancient Observatory"}, {"type", "museum"}, } )}; DocumentReference[] landmarks = Task.WhenAll(futures).Result;
Vous pouvez utiliser la requête simple et composée décrite précédemment pour interroger la sous-collection landmarks
d'une seule ville, mais vous souhaitez peut-être également extraire les résultats de la sous-collection landmarks
de chaque ville en même temps.
Le groupe de collections landmarks
est constitué de toutes les collections comportant l'ID landmarks
. Vous pouvez l'interroger à l'aide d'une requête de groupe de collections. Par exemple, cette requête de groupe de collections extrait tous les points de repère museum
dans toutes les villes :
import { collectionGroup, query, where, getDocs } from "firebase/firestore"; const museums = query(collectionGroup(db, 'landmarks'), where('type', '==', 'museum')); const querySnapshot = await getDocs(museums); querySnapshot.forEach((doc) => { console.log(doc.id, ' => ', doc.data()); });
var museums = db.collectionGroup('landmarks').where('type', '==', 'museum'); museums.get().then((querySnapshot) => { querySnapshot.forEach((doc) => { console.log(doc.id, ' => ', doc.data()); }); });
db.collectionGroup("landmarks").whereField("type", isEqualTo: "museum").getDocuments { (snapshot, error) in // ... }
[[[self.db collectionGroupWithID:@"landmarks"] queryWhereField:@"type" isEqualTo:@"museum"] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { // ... }];
db.collectionGroup("landmarks").whereEqualTo("type", "museum").get() .addOnSuccessListener { queryDocumentSnapshots -> // ... }
db.collectionGroup("landmarks").whereEqualTo("type", "museum").get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot queryDocumentSnapshots) { // ... } });
db .collectionGroup("landmarks") .where("type", isEqualTo: "museum") .get() .then( (res) => print("Successfully completed"), onError: (e) => print("Error completing: $e"), );
db->CollectionGroup("landmarks")
.WhereEqualTo("type", FieldValue::String("museum")).Get()
.OnCompletion([](const firebase::Future<QuerySnapshot>& future) {
if (future.error() == Error::kErrorOk) {
for (const DocumentSnapshot& document : future.result()->documents()) {
std::cout << document << std::endl;
}
} else {
std::cout << "Error getting documents: " << future.error_message()
<< std::endl;
}
});
Query museums = db.CollectionGroup("landmarks").WhereEqualTo("type", "museum"); museums.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask) => { foreach (DocumentSnapshot documentSnapshot in querySnapshotTask.Result.Documents) { Debug.Log(String.Format("Document {0} returned by query State=CA", documentSnapshot.Id)); } });
Avant d'utiliser une requête de groupe de collections, vous devez créer un index compatible avec celle-ci. Vous pouvez créer un index via un message d'erreur, la console ou la CLI Firebase.
Pour les SDK Web et mobiles, vous devez également créer des règles qui autorisent les requêtes de groupe de collections.
Expliquer les performances de vos requêtes
Firestore vous permet de mesurer les performances de vos requêtes sur le backend et de recevoir en retour des statistiques détaillées sur l'exécution des requêtes backend.
Les résultats de l'explication des requêtes vous aident à comprendre comment vos requêtes sont exécutées. Ils vous indiquent les inefficacités et l'emplacement des goulots d'étranglement côté serveur.
Pour en savoir plus, consultez le guide sur l'explication des requêtes.
Limites des requêtes
La liste suivante récapitule les limites des requêtes Firestore :
- Firestore est compatible avec les requêtes
OR
logiques via les opérateursor
,in
etarray-contains-any
. Ces requêtes sont limitées à 30 disjonctions en fonction de la forme normale disjonctive de la requête. - Vous ne pouvez utiliser qu'une seule clause
array-contains
par disjonction (groupeor
). Vous ne pouvez pas combinerarray-contains
avecarray-contains-any
dans la même disjonction. - Vous ne pouvez pas combiner
not-in
avecin
,array-contains-any
ouor
dans la même requête. - Un seul
not-in
ou!=
est autorisé par requête. not-in
accepte jusqu'à 10 valeurs de comparaison.- La somme des filtres, des ordres de tri et du chemin d'accès au document parent (1 pour une sous-collection, 0 pour une collection racine) dans une requête ne peut dépasser 100. Ce nombre est calculé en fonction de la forme normale disjonctive de la requête.
- Une requête avec un filtre d'inégalité sur un champ implique un tri par ce champ et filtre l'existence de ce champ.
Limites concernant les requêtes OR
Pour éviter qu'une requête ne devienne trop coûteuse en termes de calcul, Firestore limite le nombre de clauses AND
et OR
que vous pouvez combiner.
Pour appliquer cette limite, Firestore convertit les requêtes qui effectuent des opérations OR
logiques (or
, in
et array-contains-any
) en forme normale disjonctive (également appelée OR
de AND
). Firestore limite une requête à un maximum de 30 disjonctions dans la forme normale disjonctive.
Forme normale disjonctive
Firestore convertit les requêtes en forme normale disjonctive en appliquant deux règles:
Aplatir
Étant donné les conditions
A
,B
etC
:A and (B and C) => A and B and C
-
Conditions
A
,B
,C
etD
:A and (B or C) => (A and B) or (A and C)
(A or B) and (C or D) => (A and C) or (A and D) or (B and C) or (B and D)
Lorsque vous appliquez ces règles aux requêtes in
et array-contains-any
, n'oubliez pas que ces opérateurs sont des raccourcis pour OR
. Par exemple, a in [1,2]
est l'abréviation de a = 1 OR a = 2
.
Les exemples suivants indiquent le nombre de disjonctions pour différentes requêtes:
Requête | Nombre de disjonctions |
---|---|
query(collectionRef, where("a", "==", 1)) |
1 |
query(collectionRef, or( where("a", "==", 1), where("b", "==", 2) )) |
2 |
query(collectionRef, or( and( where("a", "==", 1), where("c", "==", 3) ), and( where("a", "==", 1), where("d", "==", 4) ), and( where("b", "==", 2), where("c", "==", 3) ), and( where("b", "==", 2), where("d", "==", 4) ) ) ) |
4 |
query(collectionRef, and( or( where("a", "==", 1), where("b", "==", 2) ), or( where("c", "==", 3), where("d", "==", 4) ) ) ) |
4 La forme normale disjonctive de cette requête est égale à la requête ci-dessus. |
query(collectionRef, where("a", "in", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ) |
10 |
query(collectionRef, and( where("a", "in", [1, 2, 3, 4, 5]), where("b", "in", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ) ) |
50 Cette requête renvoie une erreur, car elle dépasse la limite de 30 disjonctions. |
query(collectionRef, or( where("a", "in", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), where("b", "in", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) ) ) |
20 |
query(collectionRef, and( where("a", "in", [1, 2, 3, 4, 5]), or( where("b", "==", 2), where("c", "==", 3) ) ) ) |
10 |
orderBy
et existence
Lorsque vous triez une requête par un champ donné, elle ne peut renvoyer que les documents pour lesquels le champ de tri existe.
Par exemple, la requête suivante ne renverrait aucun document pour lequel le champ population
n'est pas défini, même s'ils répondent aux filtres de la requête.
db.collection("cities").whereEqualTo("country", “USA”).orderBy(“population”);
Un effet similaire s'applique aux inégalités. Une requête avec un filtre d'inégalité sur un champ implique également un tri par ce champ. La requête suivante ne renvoie pas de documents sans champ population
, même si country = USA
est présent dans ce document . Pour contourner ce problème, vous pouvez exécuter des requêtes distinctes pour chaque tri ou attribuer une valeur à tous les champs par lesquels vous triez.
db.collection(“cities”).where(or(“country”, USA”), greaterThan(“population”, 250000));
La requête ci-dessus inclut un ordre implicite sur l'inégalité et est équivalente à la suivante:
db.collection(“cities”).where(or(“country”, USA”), greaterThan(“population”, 250000)).orderBy(“population”);
Étape suivante
- Découvrez comment trier et limiter les données dans les résultats de requête.
- Enregistrez les lectures lorsque vous souhaitez simplement dénombrer les résultats.