Cloud 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
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
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( u'City(name={}, country={}, population={}, capital={}, regions={})' .format(self.name, self.country, self.population, self.capital, 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::FromString("San Francisco")}, {"state", FieldValue::FromString("CA")}, {"country", FieldValue::FromString("USA")}, {"capital", FieldValue::FromBoolean(false)}, {"population", FieldValue::FromInteger(860000)}, {"regions", FieldValue::FromArray({FieldValue::FromString("west_coast"), FieldValue::FromString("norcal")})}, }); cities.Document("LA").Set({ {"name", FieldValue::FromString("Los Angeles")}, {"state", FieldValue::FromString("CA")}, {"country", FieldValue::FromString("USA")}, {"capital", FieldValue::FromBoolean(false)}, {"population", FieldValue::FromInteger(3900000)}, {"regions", FieldValue::FromArray({FieldValue::FromString("west_coast"), FieldValue::FromString("socal")})}, }); cities.Document("DC").Set({ {"name", FieldValue::FromString("Washington D.C.")}, {"state", FieldValue::Null()}, {"country", FieldValue::FromString("USA")}, {"capital", FieldValue::FromBoolean(true)}, {"population", FieldValue::FromInteger(680000)}, {"regions", FieldValue::FromArray({FieldValue::FromString("east_coast")})}, }); cities.Document("TOK").Set({ {"name", FieldValue::FromString("Tokyo")}, {"state", FieldValue::Null()}, {"country", FieldValue::FromString("Japan")}, {"capital", FieldValue::FromBoolean(true)}, {"population", FieldValue::FromInteger(9000000)}, {"regions", FieldValue::FromArray({FieldValue::FromString("kanto"), FieldValue::FromString("honshu")})}, }); cities.Document("BJ").Set({ {"name", FieldValue::FromString("Beijing")}, {"state", FieldValue::Null()}, {"country", FieldValue::FromString("China")}, {"capital", FieldValue::FromBoolean(true)}, {"population", FieldValue::FromInteger(21500000)}, {"regions", FieldValue::FromArray({FieldValue::FromString("jingjinji"), FieldValue::FromString("hebei")})}, });
Node.js
let citiesRef = db.collection('cities'); let setSf = citiesRef.doc('SF').set({ name: 'San Francisco', state: 'CA', country: 'USA', capital: false, population: 860000, regions: ['west_coast', 'norcal'] }); let setLa = citiesRef.doc('LA').set({ name: 'Los Angeles', state: 'CA', country: 'USA', capital: false, population: 3900000, regions: ['west_coast', 'socal'] }); let setDc = citiesRef.doc('DC').set({ name: 'Washington, D.C.', state: null, country: 'USA', capital: true, population: 680000, regions: ['east_coast'] }); let setTok = citiesRef.doc('TOK').set({ name: 'Tokyo', state: null, country: 'Japan', capital: true, population: 9000000, regions: ['kanto', 'honshu'] }); let setBj = 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 "cities" cities_ref.doc("SF").set( name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860_000 ) cities_ref.doc("LA").set( name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3_900_000 ) cities_ref.doc("DC").set( name: "Washington D.C.", state: nil, country: "USA", capital: true, population: 680_000 ) cities_ref.doc("TOK").set( name: "Tokyo", state: nil, country: "Japan", capital: true, population: 9_000_000 ) cities_ref.doc("BJ").set( name: "Beijing", state: nil, country: "China", capital: true, population: 21_500_000 )
简单查询
以下查询会返回 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
// 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
// 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::FromString("CA"));
Node.js
// Create a reference to the cities collection let citiesRef = db.collection('cities'); // Create a query against the collection let 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 "cities" 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
Query capitalCities = db.collection("cities").whereEqualTo("capital", true);
Kotlin+KTX
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::FromBoolean(true));
Node.js
// Create a reference to the cities collection let citiesRef = db.collection('cities'); // Create a query against the collection let queryRef = citiesRef.where('capital', '==', true);
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 "cities" 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
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
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
docs = db.collection(u'cities').where(u'capital', u'==', True).stream() for doc in docs: print(u'{} => {}'.format(doc.id, doc.to_dict()))
C++
db->Collection("cities") .WhereEqualTo("capital", FieldValue::FromBoolean(true)) .Get() .OnCompletion([](const Future<QuerySnapshot>& future) { if (future.error() == Error::Ok) { for (const DocumentSnapshot& document : future.result()->documents()) { std::cout << document << '\n'; } } else { std::cout << "Error getting documents: " << future.error_message() << '\n'; } });
Node.js
let citiesRef = db.collection('cities'); let query = citiesRef.where('capital', '==', true).get() .then(snapshot => { if (snapshot.empty) { console.log('No matching documents.'); return; } snapshot.forEach(doc => { console.log(doc.id, '=>', doc.data()); }); }) .catch(err => { console.log('Error getting documents', err); });
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 "cities" query = cities_ref.where "capital", "=", true query.get do |city| puts "#{city.document_id} data: #{city.data}." end
如需详细了解如何检索查询结果,请参阅获取数据。您还可以向查询中添加监听器,以获取当前结果并监听以后的更新。
查询运算符
where()
方法会传递三个参数:作为过滤依据的字段、比较运算符和值。比较运算符可以是 <
、<=
、==
、>
、>=
、array-contains
、in
或 array-contains-any
。对于 iOS、Android 和 Java,比较运算符会在方法中明确指定。
下面是一些示例过滤条件:
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
citiesRef.whereEqualTo("state", "CA"); citiesRef.whereLessThan("population", 100000); citiesRef.whereGreaterThanOrEqualTo("name", "San Francisco");
Kotlin+KTX
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::FromString("CA")); cities_ref.WhereLessThan("population", FieldValue::FromInteger(100000)); cities_ref.WhereGreaterThanOrEqualTo("name", FieldValue::FromString("San Francisco"));
Node.js
let stateQuery = citiesRef.where('state', '==', 'CA'); let populationQuery = citiesRef.where('population', '<', 1000000); let nameQuery = citiesRef.where('name', '>=', 'San Francisco');
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"
数组成员
您可以使用 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
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContains("regions", "west_coast");
Kotlin+KTX
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
let westCoastCities = citiesRef.where('regions', 'array-contains', 'west_coast');
Go
query := cities.Where("regions", "array-contains", "west_coast").Documents(ctx)
PHP
$containsQuery = $citiesRef->where('regions', 'array-contains', 'west_coast');
Unity
// This is not yet supported in the Unity SDK.
C#
Query query = citiesRef.WhereArrayContains("Regions", "west_coast");
Ruby
// Not supported yet
此查询会返回每一个 regions
字段是包含 west_coast
的数组的 city
文档。对于您查询的值,如果数组具有该值的多个实例,则结果将仅包含该文档一次。
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
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereIn("country", Arrays.asList("USA", "Japan"));
Kotlin+KTX
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 = citiesRef.where('country', 'in', ['USA', 'Japan']);
Go
cities := client.Collection("cities") query := cities.Where("country", "in", []string{"USA", "Japan"}).Documents(ctx)
PHP
// Snippet not yet available
Unity
// Not yet supported in the Unity SDK
C#
// Snippet not yet available
Ruby
// Snippet not yet available
此查询会返回 country
字段设置为 USA
或 Japan
的每个 city
文档。根据示例数据,这包括 SF
、LA
、DC
和 TOK
文档。
同样,使用 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
CollectionReference citiesRef = db.collection("cities"); citiesRef.whereArrayContainsAny("regions", Arrays.asList("west_coast", "east_coast"));
Kotlin+KTX
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 = citiesRef.where('regions', 'array-contains-any', ['west_coast', 'east_coast']);
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
// Not yet supported in the Unity SDK
C#
// Snippet not yet available
Ruby
// Snippet not yet available
此查询会返回每一个 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
citiesRef.whereIn("regions", Arrays.asList(new String[]{"west_coast"}, new String[]{"east_coast"}));
Kotlin+KTX
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 = citiesRef.where('region', 'in', [['west_coast', 'east_coast']]);
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#
// Snippet not yet available
Ruby
// Snippet not yet available
此查询会返回每个 region
字段是仅包含一个元素(west_coast
或 east_coast
)的数组的 city 文档。在示例数据中,只有 DC
文档符合条件,因为其 region
字段为 ["east_coast"]
。但是,SF
文档不匹配,因为其 region
字段为 ["west_coast", "norcal"]
。
限制
请注意 in
和 array-contains-any
的以下限制:
in
和array-contains-any
最多支持 10 个比较值。- 每个查询只能使用一个
in
或array-contains-any
子句。不能在同一查询中同时使用in
和array-contains-any
。 array-contains
可以与in
组合使用,但不能与array-contains-any
组合使用。- 不能按等式(
=
) 或in
子句中包含的任何字段对查询进行排序。
复合查询
您还可以将多个 where()
方法串联起来,以创建更具体的查询(逻辑 AND
)。不过,要将等式运算符 (==
) 与范围运算符或 array-contains 子句(<
、<=
、>
、>=
或 array-contains
)结合使用,请务必创建复合索引。
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
citiesRef.whereEqualTo("state", "CO").whereEqualTo("name", "Denver"); citiesRef.whereEqualTo("state", "CA").whereLessThan("population", 1000000);
Kotlin+KTX
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::FromString("CO")) .WhereEqualTo("name", FieldValue::FromString("Denver")); cities_ref.WhereEqualTo("state", FieldValue::FromString("CA")) .WhereLessThan("population", FieldValue::FromInteger(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
citiesRef.whereGreaterThanOrEqualTo("state", "CA") .whereLessThanOrEqualTo("state", "IN"); citiesRef.whereEqualTo("state", "CA") .whereGreaterThan("population", 1000000);
Kotlin+KTX
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::FromString("CA")) .WhereLessThanOrEqualTo("state", FieldValue::FromString("IN")); cities_ref.WhereEqualTo("state", FieldValue::FromString("CA")) .WhereGreaterThan("population", FieldValue::FromInteger(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
citiesRef.whereGreaterThanOrEqualTo("state", "CA").whereGreaterThan("population", 100000);
Kotlin+KTX
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::FromString("CA")) .WhereGreaterThan("population", FieldValue::FromInteger(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
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", "musuem"); 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 Musuem"); 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 Musuem 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
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
let citiesRef = db.collection('cities'); let 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' }) ]);
Go
import ( "context" "fmt" "cloud.google.com/go/firestore" ) // collectionGroupSetup sets up a collection group to query. func collectionGroupSetup(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() 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("cities") 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#
// Snippet not yet available
Ruby
// Snippet not yet available
我们可以使用之前介绍的简单查询和复合查询来查询单个城市的 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
db.collectionGroup("landmarks").whereEqualTo("type", "museum").get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot queryDocumentSnapshots) { // ... } });
Kotlin+KTX
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(u'{} => {}'.format(doc.id, doc.to_dict()))
C++
// This is not yet supported.
Node.js
let museums = db.collectionGroup('landmarks').where('type', '==', 'museum'); museums.get().then(function(querySnapshot) { querySnapshot.forEach(function(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#
// Snippet not yet available
Ruby
// Snippet not yet available
在使用集合组查询之前,您必须创建支持集合组查询的索引。您可以通过错误消息、控制台或 Firebase CLI 创建索引。
对于 Web 和移动 SDK,您还必须创建允许集合组查询的规则。
查询限制
Cloud Firestore 不支持以下类型的查询,或仅对其提供有限的支持:
- 不支持对不同字段进行范围过滤的查询。
- 不支持使用
!=
子句的查询。在这种情况下,请将查询拆分为一个“大于”查询和一个“小于”查询。例如,虽然查询子句where("age", "!=", "30")
不受支持,但您可以通过组合两个查询来获得相同的结果集:一个查询使用子句where("age", "<", "30")
,另一个查询使用子句where("age", ">", 30)
。 - Cloud Firestore 对逻辑
OR
查询提供有限的支持。in
和array-contains-any
运算符支持单个字段上最多有 10 个等式 (==
) 或array-contains
条件的逻辑OR
。在这种情况下,请为每个OR
条件创建一个单独的查询,并在应用中合并查询结果。 - 每个查询只能使用一个
in
或array-contains-any
子句。不能在同一查询中同时使用in
和array-contains-any
。 array-contains
可以与in
组合使用,但不能与array-contains-any
组合使用。- 不能按等式(
=
) 或in
子句中包含的任何字段对查询进行排序。