Firestore 提供了强大的查询功能,用于指定您要从集合或集合组中检索哪些文档。这些查询也可以与 get()
或 addSnapshotListener()
配合使用,如获取数据和获取实时更新中所述。
示例数据
首先,请编写一些关于城市的数据,以便我们确定读回这些数据的不同方式:
Web
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"] });
Swift
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"] ])
Objective-C
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"] }];
Java
Android
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);
Kotlin+KTX
Android
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)
Java
CollectionReference cities = db.collection("cities"); List<ApiFuture<WriteResult>> futures = new ArrayList<>(); futures.add( cities .document("SF") .set( new City( "San Francisco", "CA", "USA", false, 860000L, Arrays.asList("west_coast", "norcal")))); futures.add( cities .document("LA") .set( new City( "Los Angeles", "CA", "USA", false, 3900000L, Arrays.asList("west_coast", "socal")))); futures.add( cities .document("DC") .set( new City( "Washington D.C.", null, "USA", true, 680000L, Arrays.asList("east_coast")))); futures.add( cities .document("TOK") .set( new City( "Tokyo", null, "Japan", true, 9000000L, Arrays.asList("kanto", "honshu")))); futures.add( cities .document("BJ") .set( new City( "Beijing", null, "China", true, 21500000L, Arrays.asList("jingjinji", "hebei")))); // (optional) block on documents successfully added ApiFutures.allAsList(futures).get();
Python
class City(object): 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(u'cities') cities_ref.document(u'BJ').set( City(u'Beijing', None, u'China', True, 21500000, [u'hebei']).to_dict()) cities_ref.document(u'SF').set( City(u'San Francisco', u'CA', u'USA', False, 860000, [u'west_coast', u'norcal']).to_dict()) cities_ref.document(u'LA').set( City(u'Los Angeles', u'CA', u'USA', False, 3900000, [u'west_coast', u'socal']).to_dict()) cities_ref.document(u'DC').set( City(u'Washington D.C.', None, u'USA', True, 680000, [u'east_coast']).to_dict()) cities_ref.document(u'TOK').set( City(u'Tokyo', None, u'Japan', True, 9000000, [u'kanto', u'honshu']).to_dict())
C++
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")})}, });
Node.js
const citiesRef = db.collection('cities'); await citiesRef.doc('SF').set({ name: 'San Francisco', state: 'CA', country: 'USA', capital: false, population: 860000, regions: ['west_coast', 'norcal'] }); await citiesRef.doc('LA').set({ name: 'Los Angeles', state: 'CA', country: 'USA', capital: false, population: 3900000, regions: ['west_coast', 'socal'] }); await citiesRef.doc('DC').set({ name: 'Washington, D.C.', state: null, country: 'USA', capital: true, population: 680000, regions: ['east_coast'] }); await citiesRef.doc('TOK').set({ name: 'Tokyo', state: null, country: 'Japan', capital: true, population: 9000000, regions: ['kanto', 'honshu'] }); await citiesRef.doc('BJ').set({ name: 'Beijing', state: null, country: 'China', capital: true, population: 21500000, regions: ['jingjinji', 'hebei'] });
Go
cities := []struct { id string c City }{ { id: "SF", c: City{Name: "San Francisco", State: "CA", Country: "USA", Capital: false, Population: 860000, Regions: []string{"west_coast", "norcal"}}, }, { id: "LA", c: City{Name: "Los Angeles", State: "CA", Country: "USA", Capital: false, Population: 3900000, Regions: []string{"west_coast", "socal"}}, }, { id: "DC", c: City{Name: "Washington D.C.", Country: "USA", Capital: false, Population: 680000, Regions: []string{"east_coast"}}, }, { id: "TOK", c: City{Name: "Tokyo", Country: "Japan", Capital: true, Population: 9000000, Regions: []string{"kanto", "honshu"}}, }, { id: "BJ", c: City{Name: "Beijing", Country: "China", Capital: true, Population: 21500000, Regions: []string{"jingjinji", "hebei"}}, }, } for _, c := range cities { if _, err := client.Collection("cities").Doc(c.id).Set(ctx, c.c); err != nil { return err } }
PHP
$citiesRef = $db->collection('cities'); $citiesRef->document('SF')->set([ 'name' => 'San Francisco', 'state' => 'CA', 'country' => 'USA', 'capital' => false, 'population' => 860000, 'regions' => ['west_coast', 'norcal'] ]); $citiesRef->document('LA')->set([ 'name' => 'Los Angeles', 'state' => 'CA', 'country' => 'USA', 'capital' => false, 'population' => 3900000, 'regions' => ['west_coast', 'socal'] ]); $citiesRef->document('DC')->set([ 'name' => 'Washington D.C.', 'state' => null, 'country' => 'USA', 'capital' => true, 'population' => 680000, 'regions' => ['east_coast'] ]); $citiesRef->document('TOK')->set([ 'name' => 'Tokyo', 'state' => null, 'country' => 'Japan', 'capital' => true, 'population' => 9000000, 'regions' => ['kanto', 'honshu'] ]); $citiesRef->document('BJ')->set([ 'name' => 'Beijing', 'state' => null, 'country' => 'China', 'capital' => true, 'population' => 21500000, 'regions' => ['jingjinji', 'hebei'] ]); printf('Added example cities data to the cities collection.' . PHP_EOL);
Unity
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"} } });
C#
CollectionReference citiesRef = db.Collection("cities"); await 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"} } }); await 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"} } }); await 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"} } }); await citiesRef.Document("TOK").SetAsync(new Dictionary<string, object>(){ { "Name", "Tokyo" }, { "State", null }, { "Country", "Japan" }, { "Capital", true }, { "Population", 9000000 }, { "Regions", new ArrayList{"kanto", "honshu"} } }); await citiesRef.Document("BJ").SetAsync(new Dictionary<string, object>(){ { "Name", "Beijing" }, { "State", null }, { "Country", "China" }, { "Capital", true }, { "Population", 21500000 }, { "Regions", new ArrayList{"jingjinji", "hebei"} } }); Console.WriteLine("Added example cities data to the cities collection.");
Ruby
cities_ref = firestore.col collection_path cities_ref.doc("SF").set( name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860_000, regions: ["west_coast", "norcal"] ) cities_ref.doc("LA").set( name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3_900_000, regions: ["west_coast", "socal"] ) cities_ref.doc("DC").set( name: "Washington D.C.", state: nil, country: "USA", capital: true, population: 680_000, regions: ["east_coast"] ) cities_ref.doc("TOK").set( name: "Tokyo", state: nil, country: "Japan", capital: true, population: 9_000_000, regions: ["kanto", "honshu"] ) cities_ref.doc("BJ").set( name: "Beijing", state: nil, country: "China", capital: true, population: 21_500_000, regions: ["jingjinji", "hebei"] )
简单查询
以下查询会返回 CA
州的所有城市:
Web
// Create a reference to the cities collection var citiesRef = db.collection("cities"); // Create a query against the collection. var query = citiesRef.where("state", "==", "CA");
Swift
// 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")
Objective-C
// 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"];
Java
Android
// Create a reference to the cities collection CollectionReference citiesRef = db.collection("cities"); // Create a query against the collection. Query query = citiesRef.whereEqualTo("state", "CA");
Kotlin+KTX
Android
// Create a reference to the cities collection val citiesRef = db.collection("cities") // Create a query against the collection. val query = citiesRef.whereEqualTo("state", "CA")
Java
// Create a reference to the cities collection CollectionReference cities = db.collection("cities"); // Create a query against the collection. Query query = cities.whereEqualTo("state", "CA"); // retrieve query results asynchronously using query.get() ApiFuture<QuerySnapshot> querySnapshot = query.get(); for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { System.out.println(document.getId()); }
Python
# Create a reference to the cities collection cities_ref = db.collection(u'cities') # Create a query against the collection query_ref = cities_ref.where(u'state', u'==', u'CA')
C++
CollectionReference cities_ref = db->Collection("cities"); // Create a query against the collection. Query query_ca = cities_ref.WhereEqualTo("state", FieldValue::String("CA"));
Node.js
// Create a reference to the cities collection const citiesRef = db.collection('cities'); // Create a query against the collection const queryRef = citiesRef.where('state', '==', 'CA');
Go
query := client.Collection("cities").Where("state", "==", "CA")
PHP
$citiesRef = $db->collection('cities'); $query = $citiesRef->where('state', '=', 'CA'); $snapshot = $query->documents(); foreach ($snapshot as $document) { printf('Document %s returned by query state=CA' . PHP_EOL, $document->id()); }
Unity
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)); } });
C#
CollectionReference citiesRef = db.Collection("cities"); Query query = citiesRef.WhereEqualTo("State", "CA"); QuerySnapshot querySnapshot = await query.GetSnapshotAsync(); foreach (DocumentSnapshot documentSnapshot in querySnapshot.Documents) { Console.WriteLine("Document {0} returned by query State=CA", documentSnapshot.Id); }
Ruby
cities_ref = firestore.col collection_path query = cities_ref.where "state", "=", "CA" query.get do |city| puts "Document #{city.document_id} returned by query state=CA." end
以下查询会返回所有首都:
Web
var citiesRef = db.collection("cities"); var query = citiesRef.where("capital", "==", true);
Swift
let capitalCities = db.collection("cities").whereField("capital", isEqualTo: true)
Objective-C
FIRQuery *capitalCities = [[self.db collectionWithPath:@"cities"] queryWhereField:@"capital" isEqualTo:@YES];
Java
Android
Query capitalCities = db.collection("cities").whereEqualTo("capital", true);
Kotlin+KTX
Android
val capitalCities = db.collection("cities").whereEqualTo("capital", true)
Java
// Create a reference to the cities collection CollectionReference cities = db.collection("cities"); // Create a query against the collection. Query query = cities.whereEqualTo("capital", true); // retrieve query results asynchronously using query.get() ApiFuture<QuerySnapshot> querySnapshot = query.get(); for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { System.out.println(document.getId()); }
Python
cities_ref = db.collection(u'cities') query = cities_ref.where(u'capital', u'==', True)
C++
Query capital_cities = db->Collection("cities").WhereEqualTo( "capital", FieldValue::Boolean(true));
Node.js
// Create a reference to the cities collection const citiesRef = db.collection('cities'); // Create a query against the collection const allCapitalsRes = await citiesRef.where('capital', '==', true).get();
Go
query := client.Collection("cities").Where("capital", "==", true)
PHP
$citiesRef = $db->collection('cities'); $query = $citiesRef->where('capital', '=', true); $snapshot = $query->documents(); foreach ($snapshot as $document) { printf('Document %s returned by query capital=true' . PHP_EOL, $document->id()); }
Unity
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)); } });
C#
CollectionReference citiesRef = db.Collection("cities"); Query query = citiesRef.WhereEqualTo("Capital", true); QuerySnapshot querySnapshot = await query.GetSnapshotAsync(); foreach (DocumentSnapshot documentSnapshot in querySnapshot.Documents) { Console.WriteLine("Document {0} returned by query Capital=true", documentSnapshot.Id); }
Ruby
cities_ref = firestore.col collection_path query = cities_ref.where "capital", "=", true query.get do |city| puts "Document #{city.document_id} returned by query capital=true." end
执行查询
创建查询对象后,使用 get()
函数检索结果:
Web
db.collection("cities").where("capital", "==", true) .get() .then(function(querySnapshot) { querySnapshot.forEach(function(doc) { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); }); }) .catch(function(error) { console.log("Error getting documents: ", error); });
Swift
db.collection("cities").whereField("capital", isEqualTo: true) .getDocuments() { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") } else { for document in querySnapshot!.documents { print("\(document.documentID) => \(document.data())") } } }
Objective-C
[[[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); } } }];
Java
Android
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()); } } });
Kotlin+KTX
Android
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) }
Java
//asynchronously retrieve multiple documents ApiFuture<QuerySnapshot> future = db.collection("cities").whereEqualTo("capital", true).get(); // future.get() blocks on response List<QueryDocumentSnapshot> documents = future.get().getDocuments(); for (DocumentSnapshot document : documents) { System.out.println(document.getId() + " => " + document.toObject(City.class)); }
Python
# Note: Use of CollectionRef stream() is prefered to get() docs = db.collection(u'cities').where(u'capital', u'==', True).stream() for doc in docs: print(f'{doc.id} => {doc.to_dict()}')
C++
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 << '\n'; } } else { std::cout << "Error getting documents: " << future.error_message() << '\n'; } });
Node.js
const citiesRef = db.collection('cities'); const snapshot = await citiesRef.where('capital', '==', true).get(); if (snapshot.empty) { console.log('No matching documents.'); return; } snapshot.forEach(doc => { console.log(doc.id, '=>', doc.data()); });
Go
fmt.Println("All capital cities:") iter := client.Collection("cities").Where("capital", "==", true).Documents(ctx) for { doc, err := iter.Next() if err == iterator.Done { break } if err != nil { return err } fmt.Println(doc.Data()) }
PHP
$citiesRef = $db->collection('cities'); $query = $citiesRef->where('capital', '=', true); $documents = $query->documents(); foreach ($documents as $document) { if ($document->exists()) { printf('Document data for document %s:' . PHP_EOL, $document->id()); print_r($document->data()); printf(PHP_EOL); } else { printf('Document %s does not exist!' . PHP_EOL, $snapshot->id()); } }
Unity
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(""); }; });
C#
Query capitalQuery = db.Collection("cities").WhereEqualTo("Capital", true); QuerySnapshot capitalQuerySnapshot = await capitalQuery.GetSnapshotAsync(); foreach (DocumentSnapshot documentSnapshot in capitalQuerySnapshot.Documents) { Console.WriteLine("Document data for {0} document:", documentSnapshot.Id); Dictionary<string, object> city = documentSnapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Console.WriteLine("{0}: {1}", pair.Key, pair.Value); } Console.WriteLine(""); }
Ruby
cities_ref = firestore.col collection_path query = cities_ref.where "capital", "=", true query.get do |city| puts "#{city.document_id} data: #{city.data}." end
如需详细了解如何检索查询结果,请参阅获取数据。您还可以向查询中添加监听器,以获取当前结果并监听以后的更新。
查询运算符
where()
方法使用三个参数:作为过滤依据的字段、比较运算符和值。Firestore 支持以下比较运算符:
<
小于<=
小于或等于==
等于>
大于>=
大于或等于!=
不等于array-contains
array-contains-any
in
not-in
例如:
Web
citiesRef.where("state", "==", "CA"); citiesRef.where("population", "<", 100000); citiesRef.where("name", ">=", "San Francisco");
Swift
citiesRef.whereField("state", isEqualTo: "CA") citiesRef.whereField("population", isLessThan: 100000) citiesRef.whereField("name", isGreaterThanOrEqualTo: "San Francisco")
Objective-C
[citiesRef queryWhereField:@"state" isEqualTo:@"CA"]; [citiesRef queryWhereField:@"population" isLessThan:@100000]; [citiesRef queryWhereField:@"name" isGreaterThanOrEqualTo:@"San Francisco"];
Java
Android
citiesRef.whereEqualTo("state", "CA"); citiesRef.whereLessThan("population", 100000); citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco");
Kotlin+KTX
Android
citiesRef.whereEqualTo("state", "CA") citiesRef.whereLessThan("population", 100000) citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco")
Java
Query stateQuery = cities.whereEqualTo("state", "CA"); Query populationQuery = cities.whereLessThan("population", 1000000L); Query nameQuery = cities.whereGreaterThanOrEqualTo("name", "San Francisco");
Python
cities_ref = db.collection(u'cities') cities_ref.where(u'state', u'==', u'CA') cities_ref.where(u'population', u'<', 1000000) cities_ref.where(u'name', u'>=', u'San Francisco')
C++
cities_ref.WhereEqualTo("state", FieldValue::String("CA")); cities_ref.WhereLessThan("population", FieldValue::Integer(100000)); cities_ref.WhereGreaterThanOrEqualTo("name", FieldValue::String("San Francisco"));
Node.js
const stateQueryRes = await citiesRef.where('state', '==', 'CA').get(); const populationQueryRes = await citiesRef.where('population', '<', 1000000).get(); const nameQueryRes = await citiesRef.where('name', '>=', 'San Francisco').get();
Go
countryQuery := cities.Where("state", "==", "CA") popQuery := cities.Where("population", "<", 1000000) cityQuery := cities.Where("name", ">=", "San Francisco")
PHP
$stateQuery = $citiesRef->where('state', '=', 'CA'); $populationQuery = $citiesRef->where('population', '>', 1000000); $nameQuery = $citiesRef->where('name', '>=', 'San Francisco');
Unity
Query stateQuery = citiesRef.WhereEqualTo("State", "CA"); Query populationQuery = citiesRef.WhereGreaterThan("Population", 1000000); Query nameQuery = citiesRef.WhereGreaterThanOrEqualTo("Name", "San Francisco");
C#
Query stateQuery = citiesRef.WhereEqualTo("State", "CA"); Query populationQuery = citiesRef.WhereGreaterThan("Population", 1000000); Query nameQuery = citiesRef.WhereGreaterThanOrEqualTo("Name", "San Francisco");
Ruby
state_query = cities_ref.where "state", "=", "CA" population_query = cities_ref.where "population", ">", 1_000_000 name_query = cities_ref.where "name", ">=", "San Francisco"
不等于 (!=
)
使用不等于 (!=
) 运算符返回给定字段存在且不匹配比较值的文档。例如:
Web
citiesRef.where("capital", "!=", false);
Swift
let notEqualQuery = citiesRef.whereField("capital", isNotEqualTo: false)
Objective-C
query = [citiesRef queryWhereField:@"capital" isNotEqualTo:@NO];
Java
Android
citiesRef.whereNotEqualTo("capital", false);
Kotlin+KTX
Android
citiesRef.whereNotEqualTo("capital", false)
Java
CollectionReference citiesRef = db.collection("cities"); Query query = citiesRef.whereNotEqualTo("capital", false);
Python
// Snippet not yet available
C++
// Snippet not yet available
Node.js
const capitalNotFalseRes = await citiesRef.where('capital', '!=', false).get();
Go
// Snippet not yet available
PHP
// Snippet not yet available
Unity
// Snippet not yet available
C#
// Snippet not yet available
Ruby
// Snippet not yet available
此查询会返回每一个 capital
字段存在且值不是 false
或 null
的 city
文档。这包括 capital
字段值等于 true
或除 null
以外的任何非布尔值的 city
文档。
此查询不会返回 capital
字段不存在的 city
文档。不等于 (!=
) 和 not-in
查询会排除给定字段不存在的文档。
如果一个字段被设置为任意值,包括空字符串 (""
)、null
、NaN
(非数字),则该字段存在。请注意,null
字段值与 !=
子句不匹配,因为 x != null
的计算结果为 undefined
。
限制
请注意 !=
查询的以下限制:
- 只有给定字段存在的文档才能与查询匹配。
- 您不能在复合查询中组合使用
not-in
和!=
。 - 在复合查询中,范围(
<
、<=
、>
、>=
)和!=
比较必须过滤相同的字段。
数组成员
您可以使用 array-contains
运算符以根据数组值进行过滤。例如:
Web
citiesRef.where("regions", "array-contains", "west_coast");
Swift
citiesRef .whereField("regions", arrayContains: "west_coast")
Objective-C
[citiesRef queryWhereField:@"state" arrayContains:@"west_coast"];
Java
Android
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContains("regions", "west_coast");
Kotlin+KTX
Android
val citiesRef = db.collection("cities") citiesRef.whereArrayContains("regions", "west_coast")
Java
CollectionReference citiesRef = db.collection("cities"); Query westCoastQuery = citiesRef.whereArrayContains("regions", "west_coast");
Python
cities_ref = db.collection(u'cities') query = cities_ref.where(u'regions', u'array_contains', u'west_coast')
C++
// This is not yet supported.
Node.js
const westCoastCities = citiesRef.where('regions', 'array-contains', 'west_coast').get();
Go
query := cities.Where("regions", "array-contains", "west_coast").Documents(ctx)
PHP
$containsQuery = $citiesRef->where('regions', 'array-contains', 'west_coast');
Unity
CollectionReference citiesRef = db.Collection("cities"); Query arrayContainsQuery = citiesRef.WhereArrayContains("region", "west_coast");
C#
Query query = citiesRef.WhereArrayContains("Regions", "west_coast");
Ruby
cities_ref = firestore.col collection_path cities = cities_ref.where "regions", "array-contains", "west_coast"
此查询会返回每一个 regions
字段是包含 west_coast
的数组的 city
文档。对于您查询的值,如果数组具有该值的多个实例,则结果将仅包含该文档一次。
每个查询最多只能使用一个 array-contains
子句。不能组合使用 array-contains
和 array-contains-any
。
in
、not-in
和array-contains-any
使用 in
运算符可将同一字段上的最多 10 个等式 (==
) 子句与逻辑 OR
进行组合。in
查询会返回给定字段与任意比较值匹配的文档。例如:
Web
citiesRef.where('country', 'in', ['USA', 'Japan']);
Swift
let citiesRef = db.collection("cities") citiesRef.whereField("country", in: ["USA", "Japan"])
Objective-C
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [citiesRef queryWhereField:@"country" in:@[@"USA", @"Japan"]];
Java
Android
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereIn("country", Arrays.asList("USA", "Japan"));
Kotlin+KTX
Android
val citiesRef = db.collection("cities") citiesRef.whereIn("country", listOf("USA", "Japan"))
Java
CollectionReference citiesRef = db.collection("cities"); Query query = citiesRef.whereIn("country", Arrays.asList("USA", "Japan"));
Python
cities_ref = db.collection(u'cities') query = cities_ref.where(u'country', u'in', [u'USA', u'Japan']) return query
C++
// This is not yet supported.
Node.js
const usaOrJapan = await citiesRef.where('country', 'in', ['USA', 'Japan']).get();
Go
cities := client.Collection("cities") query := cities.Where("country", "in", []string{"USA", "Japan"}).Documents(ctx)
PHP
// Snippet not yet available
Unity
CollectionReference citiesRef = db.Collection("cities"); ListcountriesList = new List<object>() {"USA", "Japan"}; Query whereInQuery = citiesRef.WhereIn("country", contriesList);
C#
Query query = citiesRef.WhereIn("Country", new[] { "USA", "Japan" });
Ruby
cities_ref = firestore.col collection_path usr_or_japan = cities_ref.where "country", "in", ["USA", "Japan"]
此查询会返回 country
字段设置为 USA
或 Japan
的每个 city
文档。根据示例数据,这包括 SF
、LA
、DC
和 TOK
文档。
not-in
使用 not-in
运算符可将同一字段上的最多 10 个不等于 (!=
) 子句与逻辑 AND
进行组合。not-in
查询返回给定字段存在但非 null
,并且不匹配任何比较值的文档。例如:
Web
citiesRef.where('country', 'not-in', ['USA', 'Japan']);
Swift
citiesRef.whereField("country", notIn: ["USA", "Japan"])
Objective-C
[citiesRef queryWhereField:@"country" notIn:@[@"USA", @"Japan"]];
Java
Android
citiesRef.whereNotIn("country", Arrays.asList("USA", "Japan"));
Kotlin+KTX
Android
citiesRef.whereNotIn("country", listOf("USA", "Japan"))
Java
CollectionReference citiesRef = db.collection("cities"); Query query = citiesRef.whereNotIn("country", Arrays.asList("USA", "Japan"));
Python
// Snippet not yet available
C++
// Snippet not yet available
Node.js
const notUsaOrJapan = await citiesRef.where('country', 'not-in', ['USA', 'Japan']).get();
Go
// Snippet not yet available
PHP
// Snippet not yet available
Unity
// Snippet not yet available
C#
// Snippet not yet available
Ruby
// Snippet not yet available
此查询会返回每一个 country
字段存在并且未设置为 USA
、Japan
或 null
的 city
文档。根据示例数据,这包括 London
和 Hong Kong
文档。
not-in
查询会排除给定字段不存在的文档。如果一个字段被设置为任意值,包括空字符串 (""
)、null
、NaN
(非数字),则该字段存在。请注意,x != null
的计算结果为 undefined
。使用 null
作为比较值之一的 not-in
查询不匹配任何文档。
array-contains-any
使用 array-contains-any
运算符可将同一字段上的最多 10 个 array-contains
子句与逻辑 OR
进行组合。array-contains-any
查询会返回文档,其中给定字段是包含一个或多个比较值的数组:
Web
citiesRef.where('regions', 'array-contains-any', ['west_coast', 'east_coast']);
Swift
let citiesRef = db.collection("cities") citiesRef.whereField("regions", arrayContainsAny: ["west_coast", "east_coast"])
Objective-C
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [citiesRef queryWhereField:@"regions" arrayContainsAny:@[@"west_coast", @"east_coast"]];
Java
Android
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContainsAny("regions", Arrays.asList("west_coast", "east_coast"));
Kotlin+KTX
Android
val citiesRef = db.collection("cities") citiesRef.whereArrayContainsAny("regions", listOf("west_coast", "east_coast"))
Java
CollectionReference citiesRef = db.collection("cities"); Query query = citiesRef.whereArrayContainsAny("regions", Arrays.asList("west_coast", "east_coast"));
Python
cities_ref = db.collection(u'cities') query = cities_ref.where( u'regions', u'array_contains_any', [u'west_coast', u'east_coast'] ) return query
C++
// This is not yet supported.
Node.js
const coastalCities = await citiesRef.where('regions', 'array-contains-any', ['west_coast', 'east_coast']).get();
Go
cities := client.Collection("cities") query := cities.Where("regions", "array-contains-any", []string{"west_coast", "east_coast"}).Documents(ctx)
PHP
// Snippet not yet available
Unity
CollectionReference citiesRef = db.Collection("cities"); ListregionsList = new List<object>() {"west_coast", "east_coast"}; Query arrayContainsAnyQuery = citiesRef.WhereArrayContainsAny("regions", regionsList);
C#
Query query = citiesRef.WhereArrayContainsAny("Regions", new[] { "west_coast", "east_coast" });
Ruby
cities_ref = firestore.col collection_path costal_cities = cities_ref.where "regions", "array-contains-any", ["west_coast", "east_coast"]
此查询会返回每一个 region
字段是包含 west_coast
或 east_coast
的数组的 city 文档。根据示例数据,这包括 SF
、LA
和 DC
文档。
来自 array-contains-any
的结果会被去重。即使文档的数组字段匹配多个比较值,结果集也仅包含该文档一次。
array-contains-any
始终按数组数据类型进行过滤。例如,上面的查询不会返回 region
字段不是数组而是字符串 west_coast
的 city 文档。
您可以将数组值用作 in
的比较值,但与 array-contains-any
不同,子句查找的是与数组长度、顺序和值完全匹配项。例如:
Web
citiesRef.where('region', 'in', [['west_coast', 'east_coast']]);
Swift
citiesRef.whereField("regions", in: [["west_coast"], ["east_coast"]]);
Objective-C
[citiesRef queryWhereField:@"regions" in:@[@[@"west_coast"], @[@"east_coast"]]];
Java
Android
citiesRef.whereIn("regions", Arrays.asList(new String[]{"west_coast"}, new String[]{"east_coast"}));
Kotlin+KTX
Android
citiesRef.whereIn("regions", listOf(arrayOf("west_coast"), arrayOf("east_coast")))
Java
CollectionReference citiesRef = db.collection("cities"); Query query = citiesRef.whereIn( "regions", Arrays.asList(Arrays.asList("west_coast"), Arrays.asList("east_coast")));
Python
cities_ref = db.collection(u'cities') query = cities_ref.where( u'regions', u'in', [[u'west_coast'], [u'east_coast']] ) return query
C++
// This is not yet supported.
Node.js
const exactlyOneCoast = await citiesRef.where('region', 'in', [['west_coast', 'east_coast']]).get();
Go
cities := client.Collection("cities") query := cities.Where("regions", "in", [][]string{{"west_coast"}, {"east_coast"}}).Documents(ctx)
PHP
// Snippet not yet available
Unity
// Not yet supported in the Unity SDK
C#
Query query = citiesRef.WhereIn("Regions", new[] { new[] { "west_coast" }, new[] { "east_coast" } });
Ruby
cities_ref = firestore.col collection_path exactly_one_cost = cities_ref.where "regions", "in", [["west_coast"], ["east_coast"]]
此查询会返回每个 region
字段是仅包含一个元素(west_coast
或 east_coast
)的数组的 city 文档。在示例数据中,只有 DC
文档符合条件,因为其 region
字段为 ["east_coast"]
。但是,SF
文档不匹配,因为其 region
字段为 ["west_coast", "norcal"]
。
限制
请注意 in
、not-in
、array-contains-any
的以下限制:
in
、not-in
、array-contains-any
最多支持 10 个比较值。- 每个查询最多只能使用一个
array-contains
子句。不能组合使用array-contains
和array-contains-any
。 - 每个查询最多只能使用一个
in
、not-in
或array-contains-any
子句。不能在同一查询中组合这些运算符。 - 不能组合使用
not-in
和不等于!=
。 - 不能按等式 (
==
) 或in
子句中包含的字段对查询进行排序。
复合查询
您可以串连多个等式运算符(==
或 array-contains
)方法以创建更具体的查询(逻辑 AND
)。但是,要将等式运算符与不等式运算符 <
、<=
、>
、!=
组合使用,您必须创建复合索引。
Web
citiesRef.where("state", "==", "CO").where("name", "==", "Denver"); citiesRef.where("state", "==", "CA").where("population", "<", 1000000);
Swift
citiesRef .whereField("state", isEqualTo: "CO") .whereField("name", isEqualTo: "Denver") citiesRef .whereField("state", isEqualTo: "CA") .whereField("population", isLessThan: 1000000)
Objective-C
[[citiesRef queryWhereField:@"state" isEqualTo:@"CO"] queryWhereField:@"name" isGreaterThanOrEqualTo:@"Denver"]; [[citiesRef queryWhereField:@"state" isEqualTo:@"CA"] queryWhereField:@"population" isLessThan:@1000000];
Java
Android
citiesRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver"); citiesRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000);
Kotlin+KTX
Android
citiesRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver") citiesRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000)
Java
Query chainedQuery1 = cities.whereEqualTo("state", "CO").whereEqualTo("name", "Denver"); Query chainedQuery2 = cities.whereEqualTo("state", "CA").whereLessThan("population", 1000000L);
Python
cities_ref = db.collection(u'cities') denver_query = cities_ref.where( u'state', u'==', u'CO').where(u'name', u'==', u'Denver') large_us_cities_query = cities_ref.where( u'state', u'==', u'CA').where(u'population', u'>', 1000000)
C++
cities_ref.WhereEqualTo("state", FieldValue::String("CO")) .WhereEqualTo("name", FieldValue::String("Denver")); cities_ref.WhereEqualTo("state", FieldValue::String("CA")) .WhereLessThan("population", FieldValue::Integer(1000000));
Node.js
citiesRef.where('state', '==', 'CO').where('name', '==', 'Denver'); citiesRef.where('state', '==', 'CA').where('population', '<', 1000000);
Go
denverQuery := cities.Where("name", "==", "Denver").Where("state", "==", "CO") caliQuery := cities.Where("state", "==", "CA").Where("population", "<=", 1000000) query := cities.Where("country", "==", "USA").Where("population", ">", 5000000)
PHP
$chainedQuery = $citiesRef ->where('state', '=', 'CA') ->where('name', '=', 'San Francisco'); $chainedQuery = $citiesRef ->where('state', '=', 'CA') ->where('population', '<', 1000000);
Unity
Query chainedQuery = citiesRef .WhereEqualTo("State", "CA") .WhereEqualTo("Name", "San Francisco"); Query chainedQuery = citiesRef .WhereEqualTo("State", "CA") .WhereLessThan("Population", 1000000);
C#
Query chainedQuery = citiesRef .WhereEqualTo("State", "CA") .WhereEqualTo("Name", "San Francisco"); Query chainedQuery = citiesRef .WhereEqualTo("State", "CA") .WhereLessThan("Population", 1000000);
Ruby
chained_query = cities_ref.where("state", "=", "CA").where("name", "=", "San Francisco") chained_query = cities_ref.where("state", "=", "CA").where("population", "<", 1_000_000)
只能对单个字段执行范围(<
、<=
、>
、>=
)或不等于 (!=
) 比较,并且一个复合查询中最多只能包含一个 array-contains
或 array-contains-any
子句:
有效:范围过滤器仅针对一个字段
Web
citiesRef.where("state", ">=", "CA").where("state", "<=", "IN"); citiesRef.where("state", "==", "CA").where("population", ">", 1000000);
Swift
citiesRef .whereField("state", isGreaterThanOrEqualTo: "CA") .whereField("state", isLessThanOrEqualTo: "IN") citiesRef .whereField("state", isEqualTo: "CA") .whereField("population", isGreaterThan: 1000000)
Objective-C
[[citiesRef queryWhereField:@"state" isGreaterThanOrEqualTo:@"CA"] queryWhereField:@"state" isLessThanOrEqualTo:@"IN"]; [[citiesRef queryWhereField:@"state" isEqualTo:@"CA"] queryWhereField:@"population" isGreaterThan:@1000000];
Java
Android
citiesRef.whereGreaterThanOrEqualTo("state", "CA") .whereLessThanOrEqualTo("state", "IN"); citiesRef.whereEqualTo("state", "CA") .whereGreaterThan("population", 1000000);
Kotlin+KTX
Android
citiesRef.whereGreaterThanOrEqualTo("state", "CA") .whereLessThanOrEqualTo("state", "IN") citiesRef.whereEqualTo("state", "CA") .whereGreaterThan("population", 1000000)
Java
Query validQuery1 = cities.whereGreaterThanOrEqualTo("state", "CA").whereLessThanOrEqualTo("state", "IN"); Query validQuery2 = cities.whereEqualTo("state", "CA").whereGreaterThan("population", 1000000);
Python
cities_ref = db.collection(u'cities') cities_ref.where(u'state', u'>=', u'CA').where(u'state', u'<=', u'IN')
C++
cities_ref.WhereGreaterThanOrEqualTo("state", FieldValue::String("CA")) .WhereLessThanOrEqualTo("state", FieldValue::String("IN")); cities_ref.WhereEqualTo("state", FieldValue::String("CA")) .WhereGreaterThan("population", FieldValue::Integer(1000000));
Node.js
citiesRef.where('state', '>=', 'CA').where('state', '<=', 'IN'); citiesRef.where('state', '==', 'CA').where('population', '>', 1000000);
Go
stateQuery := cities.Where("state", ">=", "CA").Where("state", "<", "IN") populationQuery := cities.Where("state", "==", "CA").Where("population", ">", 1000000)
PHP
$rangeQuery = $citiesRef ->where('state', '>=', 'CA') ->where('state', '<=', 'IN');
Unity
Query rangeQuery = citiesRef .WhereGreaterThanOrEqualTo("State", "CA") .WhereLessThanOrEqualTo("State", "IN");
C#
Query rangeQuery = citiesRef .WhereGreaterThanOrEqualTo("State", "CA") .WhereLessThanOrEqualTo("State", "IN");
Ruby
range_query = cities_ref.where("state", ">=", "CA").where("state", "<=", "IN")
无效:范围过滤器针对的是不同字段
Web
citiesRef.where("state", ">=", "CA").where("population", ">", 100000);
Swift
citiesRef .whereField("state", isGreaterThanOrEqualTo: "CA") .whereField("population", isGreaterThan: 1000000)
Objective-C
[[citiesRef queryWhereField:@"state" isGreaterThanOrEqualTo:@"CA"] queryWhereField:@"population" isGreaterThan:@1000000];
Java
Android
citiesRef.whereGreaterThanOrEqualTo("state", "CA").whereGreaterThan("population", 100000);
Kotlin+KTX
Android
citiesRef.whereGreaterThanOrEqualTo("state", "CA") .whereGreaterThan("population", 100000)
Java
Query invalidRangeQuery = cities.whereGreaterThanOrEqualTo("state", "CA").whereGreaterThan("population", 100000);
Python
cities_ref = db.collection(u'cities') cities_ref.where( u'state', u'>=', u'CA').where(u'population', u'>=', 1000000)
C++
// BAD EXAMPLE -- will crash the program: cities_ref.WhereGreaterThanOrEqualTo("state", FieldValue::String("CA")) .WhereGreaterThan("population", FieldValue::Integer(100000));
Node.js
citiesRef.where('state', '>=', 'CA').where('population', '>', 1000000);
Go
query := cities.Where("state", ">=", "CA").Where("population", ">", 1000000)
PHP
$invalidRangeQuery = $citiesRef ->where('state', '>=', 'CA') ->where('population', '>', 1000000);
Unity
Query invalidRangeQuery = citiesRef .WhereGreaterThanOrEqualTo("State", "CA") .WhereGreaterThan("Population", 1000000);
C#
Query invalidRangeQuery = citiesRef .WhereGreaterThanOrEqualTo("State", "CA") .WhereGreaterThan("Population", 1000000);
Ruby
invalid_range_query = cities_ref.where("state", ">=", "CA").where("population", ">", 1_000_000)
集合组查询
集合组由具有相同 ID 的所有集合组成。默认情况下,查询从数据库的单个集合中检索结果。您可以使用集合组查询从集合组(而不是从单个集合)中检索文档。
例如,您可以通过向每个城市添加地标子集来创建 landmarks
集合组:
Web
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' }) ]);
Swift
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)
Objective-C
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];
Java
Android
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);
Kotlin+KTX
Android
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)
Java
CollectionReference cities = db.collection("cities"); final List<ApiFuture<WriteResult>> futures = Arrays.asList( cities .document("SF") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Golden Gate Bridge"); put("type", "bridge"); } }), cities .document("SF") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Legion of Honor"); put("type", "museum"); } }), cities .document("LA") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Griffith Park"); put("type", "park"); } }), cities .document("LA") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "The Getty"); put("type", "museum"); } }), cities .document("DC") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Lincoln Memorial"); put("type", "memorial"); } }), cities .document("DC") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "National Air and Space Museum"); put("type", "museum"); } }), cities .document("TOK") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Ueno Park"); put("type", "park"); } }), cities .document("TOK") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "National Museum of Nature and Science"); put("type", "museum"); } }), cities .document("BJ") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Jingshan Park"); put("type", "park"); } }), cities .document("BJ") .collection("landmarks") .document() .set( new HashMap<String, String>() { { put("name", "Beijing Ancient Observatory"); put("type", "museum"); } })); final List<WriteResult> landmarks = ApiFutures.allAsList(futures).get();
Python
cities = db.collection(u'cities') sf_landmarks = cities.document(u'SF').collection(u'landmarks') sf_landmarks.document().set({ u'name': u'Golden Gate Bridge', u'type': u'bridge' }) sf_landmarks.document().set({ u'name': u'Legion of Honor', u'type': u'museum' }) la_landmarks = cities.document(u'LA').collection(u'landmarks') la_landmarks.document().set({ u'name': u'Griffith Park', u'type': u'park' }) la_landmarks.document().set({ u'name': u'The Getty', u'type': u'museum' }) dc_landmarks = cities.document(u'DC').collection(u'landmarks') dc_landmarks.document().set({ u'name': u'Lincoln Memorial', u'type': u'memorial' }) dc_landmarks.document().set({ u'name': u'National Air and Space Museum', u'type': u'museum' }) tok_landmarks = cities.document(u'TOK').collection(u'landmarks') tok_landmarks.document().set({ u'name': u'Ueno Park', u'type': u'park' }) tok_landmarks.document().set({ u'name': u'National Museum of Nature and Science', u'type': u'museum' }) bj_landmarks = cities.document(u'BJ').collection(u'landmarks') bj_landmarks.document().set({ u'name': u'Jingshan Park', u'type': u'park' }) bj_landmarks.document().set({ u'name': u'Beijing Ancient Observatory', u'type': u'museum' })
C++
// This is not yet supported.
Node.js
const citiesRef = db.collection('cities'); await citiesRef.doc('SF').collection('landmarks').doc().set({ name: 'Golden Gate Bridge', type: 'bridge' }); await citiesRef.doc('SF').collection('landmarks').doc().set({ name: 'Legion of Honor', type: 'museum' }); await citiesRef.doc('LA').collection('landmarks').doc().set({ name: 'Griffith Park', type: 'park' }); await citiesRef.doc('LA').collection('landmarks').doc().set({ name: 'The Getty', type: 'museum' }); await citiesRef.doc('DC').collection('landmarks').doc().set({ name: 'Lincoln Memorial', type: 'memorial' }); await citiesRef.doc('DC').collection('landmarks').doc().set({ name: 'National Air and Space Museum', type: 'museum' }); await citiesRef.doc('TOK').collection('landmarks').doc().set({ name: 'Ueno Park', type: 'park' }); await citiesRef.doc('TOK').collection('landmarks').doc().set({ name: 'National Museum of Nature and Science', type: 'museum' }); await citiesRef.doc('BJ').collection('landmarks').doc().set({ name: 'Jingshan Park', type: 'park' }); await citiesRef.doc('BJ').collection('landmarks').doc().set({ name: 'Beijing Ancient Observatory', type: 'museum' });
Go
import ( "context" "fmt" "cloud.google.com/go/firestore" ) // collectionGroupSetup sets up a collection group to query. func collectionGroupSetup(projectID, cityCollection string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return fmt.Errorf("firestore.NewClient: %v", err) } defer client.Close() landmarks := []struct { city, name, t string }{ {"SF", "Golden Gate Bridge", "bridge"}, {"SF", "Legion of Honor", "museum"}, {"LA", "Griffith Park", "park"}, {"LA", "The Getty", "museum"}, {"DC", "Lincoln Memorial", "memorial"}, {"DC", "National Air and Space Museum", "museum"}, {"TOK", "Ueno Park", "park"}, {"TOK", "National Museum of Nature and Science", "museum"}, {"BJ", "Jingshan Park", "park"}, {"BJ", "Beijing Ancient Observatory", "museum"}, } cities := client.Collection(cityCollection) for _, l := range landmarks { if _, err := cities.Doc(l.city).Collection("landmarks").NewDoc().Set(ctx, map[string]string{ "name": l.name, "type": l.t, }); err != nil { return fmt.Errorf("Set: %v", err) } } return nil }
PHP
// Snippet not yet available
Unity
// Not yet supported in the Unity SDK
C#
await citiesRef.Document("SF").Collection("landmarks").Document() .CreateAsync(new { Name = "Golden Gate Bridge", Type = "bridge" }); await citiesRef.Document("SF").Collection("landmarks").Document() .CreateAsync(new { Name = "Legion of Honor", Type = "museum" }); await citiesRef.Document("LA").Collection("landmarks").Document() .CreateAsync(new { Name = "Griffith Park", Type = "park" }); await citiesRef.Document("DC").Collection("landmarks").Document() .CreateAsync(new { Name = "Lincoln Memorial", Type = "memorial" }); await citiesRef.Document("DC").Collection("landmarks").Document() .CreateAsync(new { Name = "National Air And Space Museum", Type = "museum" }); await citiesRef.Document("TOK").Collection("landmarks").Document() .CreateAsync(new { Name = "Ueno Park", Type = "park" }); await citiesRef.Document("TOK").Collection("landmarks").Document() .CreateAsync(new { Name = "National Museum of Nature and Science", Type = "museum" }); await citiesRef.Document("BJ").Collection("landmarks").Document() .CreateAsync(new { Name = "Jingshan Park", Type = "park" }); await citiesRef.Document("BJ").Collection("landmarks").Document() .CreateAsync(new { Name = "Beijing Ancient Observatory", Type = "museum" });
Ruby
cities_ref = firestore.col collection_path sf_landmarks = cities_ref.document("SF").collection("landmarks") sf_landmarks.document.set( name: "Golden Gate Bridge", type: "bridge" ) sf_landmarks.document.set( name: "Legion of Honor", type: "museum" ) la_landmarks = cities_ref.document("LA").collection("landmarks") la_landmarks.document.set( name: "Griffith Park", type: "park" ) la_landmarks.document.set( name: "The Getty", type: "museum" ) dc_landmarks = cities_ref.document("DC").collection("landmarks") dc_landmarks.document.set( name: "Lincoln Memorial", type: "memorial" ) dc_landmarks.document.set( name: "National Air and Space Museum", type: "museum" ) tok_landmarks = cities_ref.document("TOK").collection("landmarks") tok_landmarks.document.set( name: "Ueno Park", type: "park" ) tok_landmarks.document.set( name: "National Museum of Nature and Science", type: "museum" ) bj_landmarks = cities_ref.document("BJ").collection("landmarks") bj_landmarks.document.set( name: "Jingshan Park", type: "park" ) bj_landmarks.document.set( name: "Beijing Ancient Observatory", type: "museum" )
我们可以使用之前介绍的简单查询和复合查询来查询单个城市的 landmarks
子集合,但您可能还需要同时从每个城市的 landmarks
子集合中检索结果。
landmarks
集合组包含 ID 为 landmarks
的所有集合,您可以使用集合组查询进行查询。例如,此集合组查询会检索所有城市的所有 museum
地标:
Web
->var museums = db.collectionGroup('landmarks').where('type', '==', 'museum'); museums.get().then(function (querySnapshot) { querySnapshot.forEach(function (doc) { console.log(doc.id, ' => ', doc.data()); }); });
Swift
db.collectionGroup("landmarks").whereField("type", isEqualTo: "museum").getDocuments { (snapshot, error) in // ... }
Objective-C
[[[self.db collectionGroupWithID:@"landmarks"] queryWhereField:@"type" isEqualTo:@"museum"] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { // ... }];
Java
Android
db.collectionGroup("landmarks").whereEqualTo("type", "museum").get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot queryDocumentSnapshots) { // ... } });
Kotlin+KTX
Android
db.collectionGroup("landmarks").whereEqualTo("type", "museum").get() .addOnSuccessListener { queryDocumentSnapshots -> // ... }
Java
final Query museums = db.collectionGroup("landmarks").whereEqualTo("type", "museum"); final ApiFuture<QuerySnapshot> querySnapshot = museums.get(); for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { System.out.println(document.getId()); }
Python
museums = db.collection_group(u'landmarks')\ .where(u'type', u'==', u'museum') docs = museums.stream() for doc in docs: print(f'{doc.id} => {doc.to_dict()}')
C++
// This is not yet supported.
Node.js
const querySnapshot = await db.collectionGroup('landmarks').where('type', '==', 'museum').get(); querySnapshot.forEach((doc) => { console.log(doc.id, ' => ', doc.data()); });
Go
import ( "context" "fmt" "io" "cloud.google.com/go/firestore" "google.golang.org/api/iterator" ) // collectionGroupQuery runs a collection group query over the data created by // collectionGroupSetup. func collectionGroupQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return fmt.Errorf("firestore.NewClient: %v", err) } defer client.Close() it := client.CollectionGroup("landmarks").Where("type", "==", "museum").Documents(ctx) for { doc, err := it.Next() if err == iterator.Done { break } if err != nil { return err } fmt.Fprintf(w, "%s: %s", doc.Ref.ID, doc.Data()["name"]) } return nil }
PHP
// Snippet not yet available
Unity
// Not yet supported in the Unity SDK
C#
Query museums = db.CollectionGroup("landmarks").WhereEqualTo("Type", "museum"); QuerySnapshot querySnapshot = await museums.GetSnapshotAsync(); foreach (DocumentSnapshot document in querySnapshot.Documents) { Console.WriteLine($"{document.Reference.Path}: {document.GetValue<string>("Name")}"); }
Ruby
museums = firestore.collection_group("landmarks").where("type", "==", "museum") museums.get do |museum| puts "#{museum[:type]} name is #{museum[:name]}." end
在使用集合组查询之前,您必须创建支持集合组查询的索引。您可以通过错误消息、控制台或 Firebase CLI 创建索引。
对于 Web 和移动 SDK,您还必须创建允许集合组查询的规则。
查询限制
以下列表总结了 Firestore 查询的限制:
- Firestore 对逻辑
OR
查询提供有限的支持。in
和array-contains-any
运算符支持单个字段上最多有 10 个等式 (==
) 或array-contains
条件的逻辑OR
。在这种情况下,请为每个OR
条件创建一个单独的查询,并在应用中合并查询结果。 - 在复合查询中,范围(
<
、<=
、>
、>=
)和不等于 (!=
) 比较必须对同一字段进行过滤。 - 每个查询最多只能使用一个
array-contains
子句。不能组合使用array-contains
和array-contains-any
。 - 每个查询最多只能使用一个
in
、not-in
或array-contains-any
子句。 不能在同一查询中组合使用in
、not-in
和array-contains-any
。 - 不能按等式 (
==
) 或in
子句中包含的字段对查询进行排序。