Consulta y filtra datos
Firestore proporciona una función de consulta potente para especificar qué documentos deseas recuperar de una colección o de un grupo de colecciones. Estas consultas también se pueden usar con get()
o addSnapshotListener()
, como se describe en Obtén datos y Obtén actualizaciones en tiempo real.
Datos de ejemplo
Para comenzar, escribe algunos datos sobre ciudades para que podamos ver las distintas maneras de leerlos:
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"} } });
Consultas simples
La siguiente consulta muestra todas las ciudades con el estado 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 siguiente consulta muestra todas las 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)); } });
Ejecuta una consulta
Después de crear un objeto de consulta, usa la función get()
para recuperar los resultados:
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
Para autenticarte en Firestore, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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(""); }; });
Consulta cómo obtener datos para obtener más información sobre cómo recuperar resultados de consultas. También puedes agregar un objeto de escucha a una consulta para obtener los resultados actuales y detectar actualizaciones futuras.
Operadores de consultas
El método where()
usa tres parámetros: un campo para filtrar, un operador de comparación y un valor. Firestore admite los siguientes operadores de comparación:
<
menor que<=
menor o igual que==
igual que>
mayor que>=
mayor o igual que!=
no igual aarray-contains
array-contains-any
in
not-in
Por ejemplo:
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");
No igual (!=
)
Usa el operador no igual (!=
) para mostrar documentos en los que el campo dado exista y que no coincida con el valor de comparación. Por ejemplo:
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
Esta consulta muestra todos los documentos de city
en los que el campo capital
existe con un valor distinto de false
o null
. Esto incluye documentos city
en los que el valor del campo capital
es igual a true
o cualquier valor no booleano además de null
.
Esta consulta no muestra documentos city
en los que el campo capital
no existe. Las consultas no igual a (!=
) y not-in
excluyen documentos en los que el campo dado no existe.
Un campo existe cuando se configura con cualquier valor, incluida una string vacía (""
), null
y NaN
(no un número). Ten en cuenta que los valores del campo null
no coinciden con las cláusulas !=
, porque x != null
se evalúa como undefined
.
Limitaciones
Ten en cuenta las limitaciones siguientes para las consultas !=
:
- Solo los documentos en los que existe el campo dado pueden coincidir con la consulta.
- No puedes combinar
not-in
y!=
en una consulta compuesta.
Membresía del arreglo
Puedes usar el operador array-contains
para filtrar en función de los valores del arreglo. Por ejemplo:
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");
Esta consulta muestra todos los documentos de city
en los que el campo regions
es un arreglo que contiene west_coast
. Si el arreglo tiene varias instancias del valor que consultaste, el documento se incluye en los resultados solo una vez.
Puedes usar como máximo una cláusula array-contains
por disyunción (grupo or
).
No puedes combinar array-contains
con array-contains-any
en la misma
disyunción.
in
, not-in
y array-contains-any
Usa el operador in
para combinar hasta 30 cláusulas de igualdad (==
) en el mismo campo con un OR
lógico. Una consulta in
muestra documentos en los que el campo dado coincide con cualquiera de los valores de comparación.
Por ejemplo:
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);
Esta consulta muestra todos los documentos city
en los que el campo country
se configura como USA
o Japan
. A partir de los datos de ejemplo, se incluyen los documentos SF
, LA
, DC
y TOK
.
not-in
Usa el operador not-in
para combinar hasta 10 cláusulas no iguales (!=
) en el mismo campo con un AND
lógico. Una consulta not-in
muestra documentos en los que el campo dado existe, no es null
y no coincide con ninguno de los valores de comparación. Por ejemplo:
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
Esta consulta muestra todos los documentos city
en los que el campo country
existe y no se configura como USA
, Japan
ni null
. A partir de los datos de ejemplo, se incluyen los documentos London
y Hong Kong
.
Las consultas not-in
excluyen los documentos en los que el campo dado no existe. Un campo existe cuando se configura con cualquier valor, incluida una string vacía (""
), null
y NaN
(no un número). Ten en cuenta que x != null
se evalúa como undefined
. Una consulta not-in
con null
como uno de los valores de comparación no coincide con ningún documento.
array-contains-any
Usa el operador array-contains-any
para combinar hasta 30 cláusulas array-contains
en el mismo campo con un OR
lógico. Una consulta
array-contains-any
muestra documentos en los que el campo dado es un array
que contiene uno o más de los valores de comparación:
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"}});
Esta consulta muestra todos los documentos de city en los que el campo regions
es un arreglo que contiene west_coast
o east_coast
. A partir de los datos de ejemplo, se incluyen los documentos SF
, LA
y DC
.
Se deducen los resultados de array-contains-any
. Aunque el campo de arreglo de un documento coincida con más de uno de los valores de comparación, el conjunto de resultados solo incluye ese documento una vez.
array-contains-any
siempre filtra por el tipo de datos del arreglo. Por ejemplo, la consulta anterior no mostraría un documento de city en el que, en lugar de un arreglo, el campo regions
sea la string west_coast
.
Puedes usar un valor de arreglo como un valor de comparación para in
, pero a diferencia de array-contains-any
, la cláusula coincide exactamente con los valores, el orden y la longitud del arreglo. Por ejemplo:
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"});
Esta consulta muestra todos los documentos de city en los que el campo regions
es un arreglo que contiene exactamente un elemento de west_coast
o east_coast
.
A partir de los datos de ejemplo, solo el documento DC
califica con su campo regions
de ["east_coast"]
. Sin embargo, el documento SF
no coincide porque su campo regions
es ["west_coast", "norcal"]
.
Limitaciones
Ten en cuenta las siguientes limitaciones para in
, not-in
y array-contains-any
.
- Firestore proporciona compatibilidad con las consultas
OR
lógicas a través de los operadoresor
,in
yarray-contains-any
. Estas consultas se limitan a 30 disyunciones según su formato disyuntivo normal. - Puedes usar como máximo una cláusula
array-contains
por disyunción (grupoor
). No puedes combinararray-contains
conarray-contains-any
en la misma disyunción. - No puedes combinar
not-in
con un no igual!=
. not-in
admite hasta 10 valores de comparación.
Consultas (AND
) compuestas
Puedes encadenar múltiples operadores de igualdad (==
o array-contains
) para combinar restricciones con un AND
lógico. Sin embargo, debes crear un índice compuesto para combinar los operadores de igualdad con los operadores de desigualdad <
, <=
, >
y !=
.
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
consultas
Puedes combinar restricciones con un OR
lógico. Por ejemplo:
const q = query(citiesRef, or(where('capital', '==', true), where('population', '>=', 1000000) ) );
No 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), ), );
El fragmento no está disponible.
El fragmento no está disponible.
El fragmento no está disponible.
const bigCities = await citiesRef .where( Filter.or( Filter.where('capital', '==', true), Filter.where('population', '>=', 1000000) ) ) .get();
El fragmento no está 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)); } });
El fragmento no está disponible.
El fragmento no está disponible.
Firestore usa tus índices compuestos para entregar consultas OR
. Si
tus índices no son compatibles con la consulta, Firestore
sugiere índices adicionales para tu base de datos.
Puedes combinar consultas OR
con consultas compuestas para filtrar las combinaciones
de operaciones OR
y AND
. Por ejemplo:
const q = query(collection(db, "cities"), and( where('state', '==', 'CA'), or( where('capital', '==', true), where('population', '>=', 1000000) ) ));
No 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), ), ), );
El fragmento no está disponible.
El fragmento no está disponible.
El fragmento no está disponible.
El fragmento no está disponible.
const bigCitiesInCalifornia = await citiesRef .where('state', '==', 'CA') .where( Filter.or( Filter.where('capital', '==', true), Filter.where('population', '>=', 1000000) ) ) .get();
El fragmento no está disponible.
El fragmento no está disponible.
Query query = citiesRef.Where(Filter.And( Filter.EqualTo("state", "CA"), Filter.Or( Filter.EqualTo("capital", true), Filter.GreaterThanOrEqualTo("population", 1000000) ) ));
El fragmento no está disponible.
El fragmento no está disponible.
Limitaciones
Ten en cuenta las limitaciones siguientes para las consultas or
:
- Firestore limita una consulta a un máximo de 30 disyunciones según su formato disyuntivo normal.
Es más probable que alcances este límite cuando realices una
AND
de varios grupos deOR
. - No puedes combinar
not-in
conin
,array-contains-any
oor
en la misma consulta.
Para obtener una descripción completa de las limitaciones, consulta Limitaciones de las consultas.
Consultas de grupos de colecciones
Un grupo de colecciones consta de todas las colecciones con el mismo ID. Según la configuración predeterminada, las consultas recuperan los resultados de una sola colección de tu base de datos. Usa una consulta de este tipo para obtener documentos de un grupo de colecciones y no de una sola colección.
Por ejemplo, para crear un grupo de colecciones de landmarks
, puedes agregar una subcolección de puntos de referencia a cada ciudad:
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;
De las consultas descritas anteriormente, podemos usar las simples para consultar la subcolección de landmarks
de una sola ciudad o las compuestas a fin de obtener los resultados de las subcolecciones landmarks
de cada ciudad de una vez.
El grupo de colecciones landmarks
consta de todas las colecciones con el ID landmarks
y se puede examinar con una consulta de grupos de colecciones. Por ejemplo, con esta consulta de grupos de colecciones se obtienen todos los puntos de referencia museum
en todas las ciudades:
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)); } });
Antes de usar una consulta de grupos de colecciones, debes crear un índice que la admita. Puedes crear un índice mediante un mensaje de error, la consola o Firebase CLI.
En el caso de los SDK para dispositivos móviles y la Web, también debes crear reglas que te permitan realizar consultas de grupos de colecciones.
Explica el rendimiento de tus consultas
Firestore te permite medir el rendimiento de tus consultas en el backend y recibir estadísticas de rendimiento detalladas sobre la ejecución de consultas de backend.
Los resultados de Query Explain te ayudan a comprender cómo se ejecutan tus consultas, lo que te muestra las ineficiencias y la ubicación de los posibles cuellos de botella del servidor.
Para obtener más información, consulta la guía de Query Explain.
Limitaciones de las consultas
La siguiente lista resume las limitaciones de las consultas de Firestore:
- Firestore proporciona compatibilidad con las consultas
OR
lógicas a través de los operadoresor
,in
yarray-contains-any
. Estas consultas se limitan a 30 disyunciones según su formato disyuntivo normal. - Puedes usar como máximo una cláusula
array-contains
por disyunción (grupoor
). No puedes combinararray-contains
conarray-contains-any
en la misma disyunción. - No puedes combinar
not-in
conin
,array-contains-any
oor
en la misma consulta. - Solo se permite un
not-in
o!=
por consulta. not-in
admite hasta 10 valores de comparación.- La suma de filtros, órdenes y la ruta del documento principal (1 para una subcolección, o 0 para una colección raíz) en una consulta no puede ser mayor que 100. Esto se calcula en función del formato disyuntivo normal de la consulta.
- Una consulta con un filtro de desigualdad en un campo implica ordenar según ese campo y filtra la existencia de ese campo.
Límites de las consultas OR
Para evitar que una consulta resulte demasiado costosa en términos de procesamiento,
Firestore limita la cantidad de cláusulas AND
y OR
que puedes combinar.
Para aplicar este límite, Firestore convierte las consultas que realizan
operaciones OR
lógicas (or
, in
yarray-contains-any
) a
formato disyuntivo normal
(también conocido como OR
de AND
). Firestore limita una consulta a un
máximo de 30 disyunciones en formato disyuntivo normal.
Formato disyuntivo normal
Firestore convierte las consultas a un formato disyuntivo normal mediante la aplicación de dos reglas:
Flatten
Dadas las condiciones
A
,B
yC
:A and (B and C) => A and B and C
-
Dadas las condiciones
A
,B
,C
yD
: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)
Cuando apliques estas reglas a las consultas in
y array-contains-any
, recuerda
que estos operadores son abreviaturas para OR
. Por ejemplo, a in [1,2]
es
la abreviatura para a = 1 OR a = 2
.
En los siguientes ejemplos, se muestra la cantidad de disyunciones para diferentes consultas:
Consulta | Cantidad de disyunciones |
---|---|
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 El formato disyuntivo normal de esta consulta es igual a la consulta anterior. |
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 Esta consulta muestra un error porque supera el límite de 30 disyunciones. |
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
y existencia
Cuando ordenas una consulta por un campo determinado, esta puede mostrar solo los documentos en los que existe el campo order-by.
Por ejemplo, la siguiente consulta no mostraría ningún documento en el que el campo
population
no esté configurado, incluso si, de lo contrario, cumple con los filtros de consulta.
db.collection("cities").whereEqualTo("country", “USA”).orderBy(“population”);
Un efecto relacionado se aplica a las desigualdades. Una consulta con un filtro de desigualdad
en un campo también implica ordenar en ese campo. La siguiente
consulta no muestra documentos sin un campo population
, incluso
si country = USA
aparece en ese documento . Como solución alternativa, puedes ejecutar
consultas separadas para cada orden o asignar un valor a todos los campos
en los aplicas un orden.
db.collection(“cities”).where(or(“country”, USA”), greaterThan(“population”, 250000));
La consulta anterior incluye un order-by implícito sobre la desigualdad y es equivalente a lo siguiente:
db.collection(“cities”).where(or(“country”, USA”), greaterThan(“population”, 250000)).orderBy(“population”);
¿Qué sigue?
- Obtén información para ordenar y limitar los datos en los resultados de la consulta.
- Guarda las lecturas cuando solo quieras contar los resultados.