Impaginazione dei dati con cursori di query

Con i cursori di query in Firestore, puoi suddividere i dati restituiti da una query in batch in base ai parametri definiti nella query.

I cursori di query definiscono i punti di inizio e di fine di una query, consentendoti di:

  • Restituisce un sottoinsieme di dati.
  • Impagina i risultati della query.

Tuttavia, per definire un intervallo specifico per una query, devi utilizzare il metodo where() descritto in Query semplici.

Aggiungere un cursore semplice a una query

Utilizza i metodi startAt() o startAfter() per definire il punto di partenza per una query. Il metodo startAt() include il punto iniziale, mentre il metodo startAfter() lo esclude.

Ad esempio, se utilizzi startAt(A) in una query, viene restituito l'intero alfabeto. Se utilizzi invece startAfter(A), restituisce B-Z.

Versione web 9

import { query, orderBy, startAt } from "firebase/firestore";

const q = query(citiesRef, orderBy("population"), startAt(1000000));

Versione web 8

citiesRef.orderBy("population").startAt(1000000);
Swift
Nota:questo prodotto non è disponibile per i target watchOS e per app clip.
// Get all cities with population over one million, ordered by population.
db.collection("cities")
    .order(by: "population")
    .start(at: [1000000])
Objective-C
Nota:questo prodotto non è disponibile per i target watchOS e per app clip.
// Get all cities with population over one million, ordered by population.
[[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"population"]
    queryStartingAtValues:@[ @1000000 ]];
Java
Android
// Get all cities with a population >= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .startAt(1000000);
Kotlin+KTX
Android
// Get all cities with a population >= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .startAt(1000000)

Freccetto

db.collection("cities").orderBy("population").startAt([1000000]);
Java
Query query = cities.orderBy("population").startAt(4921000L);
Python
cities_ref = db.collection(u'cities')
query_start_at = cities_ref.order_by(u'population').start_at({
    u'population': 1000000
})
Python
(asincrono)
cities_ref = db.collection("cities")
query_start_at = cities_ref.order_by("population").start_at({"population": 1000000})
C++
// Get all cities with a population >= 1,000,000, ordered by population,
db->Collection("cities")
    .OrderBy("population")
    .StartAt({FieldValue::Integer(1000000)});
Node.js
const startAtRes = await db.collection('cities')
  .orderBy('population')
  .startAt(1000000)
  .get();
Go
query := client.Collection("cities").OrderBy("population", firestore.Asc).StartAt(1000000)
PHP
$query = $citiesRef
    ->orderBy('population')
    ->startAt([1000000]);
Unity
Query query = citiesRef.OrderBy("Population").StartAt(1000000);
C#
Query query = citiesRef.OrderBy("Population").StartAt(1000000);
Ruby
query = cities_ref.order("population").start_at(1_000_000)

Analogamente, utilizza i metodi endAt() o endBefore() per definire un punto di arrivo per i risultati della query.

Versione web 9

import { query, orderBy, endAt } from "firebase/firestore";

const q = query(citiesRef, orderBy("population"), endAt(1000000));

Versione web 8

citiesRef.orderBy("population").endAt(1000000);
Swift
Nota: questo prodotto non è disponibile per i target watchOS e per app clip.
// Get all cities with population less than one million, ordered by population.
db.collection("cities")
    .order(by: "population")
    .end(at: [1000000])
Objective-C
Nota: questo prodotto non è disponibile per i target watchOS e per app clip.
// Get all cities with population less than one million, ordered by population.
[[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"population"]
    queryEndingAtValues:@[ @1000000 ]];
Java
Android
// Get all cities with a population <= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .endAt(1000000);
Kotlin+KTX
Android
// Get all cities with a population <= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .endAt(1000000)

Freccetto

db.collection("cities").orderBy("population").endAt([1000000]);
Java
Query query = cities.orderBy("population").endAt(4921000L);
Python
cities_ref = db.collection(u'cities')
query_end_at = cities_ref.order_by(u'population').end_at({
    u'population': 1000000
})
Python
(asincrono)
cities_ref = db.collection("cities")
query_end_at = cities_ref.order_by("population").end_at({"population": 1000000})
C++
// Get all cities with a population <= 1,000,000, ordered by population,
db->Collection("cities")
    .OrderBy("population")
    .EndAt({FieldValue::Integer(1000000)});
Node.js
const endAtRes = await db.collection('cities')
  .orderBy('population')
  .endAt(1000000)
  .get();
Go
query := client.Collection("cities").OrderBy("population", firestore.Asc).EndAt(1000000)
PHP
$query = $citiesRef
    ->orderBy('population')
    ->endAt([1000000]);
Unity
Query query = citiesRef.OrderBy("Population").EndAt(1000000);
C#
Query query = citiesRef.OrderBy("Population").EndAt(1000000);
Ruby
query = cities_ref.order("population").end_at(1_000_000)

Utilizza uno snapshot di documento per definire il cursore delle query

Puoi anche passare uno snapshot di documento alla clausola del cursore come punto di inizio o di fine del cursore di query. I valori nello snapshot del documento fungono da valori nel cursore della query.

Ad esempio, scatta un'istantanea di un documento "San Francisco" nel tuo set di dati di città e popolazioni. Quindi, utilizza l'istantanea del documento come punto di partenza per il cursore della query di compilazione. La query restituirà tutte le città con una popolazione maggiore o uguale a San Francisco, come definito nell'istantanea del documento.

Versione web 9

import { collection, doc, getDoc, query, orderBy, startAt } from "firebase/firestore";
const citiesRef = collection(db, "cities");

const docSnap = await getDoc(doc(citiesRef, "SF"));

// Get all cities with a population bigger than San Francisco
const biggerThanSf = query(citiesRef, orderBy("population"), startAt(docSnap));
// ...

Versione web 8

var citiesRef = db.collection("cities");

return citiesRef.doc("SF").get().then((doc) => {
    // Get all cities with a population bigger than San Francisco
    var biggerThanSf = citiesRef
        .orderBy("population")
        .startAt(doc);

    // ...
});
Swift
Nota: questo prodotto non è disponibile per i target watchOS e per app clip.
db.collection("cities")
    .document("SF")
    .addSnapshotListener { (document, error) in
        guard let document = document else {
            print("Error retreving cities: \(error.debugDescription)")
            return
        }

        // Get all cities with a population greater than or equal to San Francisco.
        let sfSizeOrBigger = db.collection("cities")
            .order(by: "population")
            .start(atDocument: document)
}
Objective-C
Nota: questo prodotto non è disponibile per i target watchOS e per app clip.
[[[db collectionWithPath:@"cities"] documentWithPath:@"SF"]
    addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) {
      if (snapshot == nil) {
        NSLog(@"Error retreiving cities: %@", error);
        return;
      }
      // Get all cities with a population greater than or equal to San Francisco.
      FIRQuery *sfSizeOrBigger = [[[db collectionWithPath:@"cities"]
          queryOrderedByField:@"population"]
          queryStartingAtDocument:snapshot];
    }];
Java
Android
// Get the data for "San Francisco"
db.collection("cities").document("SF")
        .get()
        .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
            @Override
            public void onSuccess(DocumentSnapshot documentSnapshot) {
                // Get all cities with a population bigger than San Francisco.
                Query biggerThanSf = db.collection("cities")
                        .orderBy("population")
                        .startAt(documentSnapshot);

                // ...
            }
        });
Kotlin+KTX
Android
// Get the data for "San Francisco"
db.collection("cities").document("SF")
        .get()
        .addOnSuccessListener { documentSnapshot ->
            // Get all cities with a population bigger than San Francisco.
            val biggerThanSf = db.collection("cities")
                    .orderBy("population")
                    .startAt(documentSnapshot)

            // ...
        }

Freccetto

db.collection("cities").doc("SF").get().then(
  (documentSnapshot) {
    final biggerThanSf = db
        .collection("cities")
        .orderBy("population")
        .startAt([documentSnapshot]);
  },
  onError: (e) => print("Error: $e"),
);
Java
// Fetch the snapshot with an API call, waiting for a maximum of 30 seconds for a result.
ApiFuture<DocumentSnapshot> future = db.collection("cities").document("SF").get();
DocumentSnapshot snapshot = future.get(30, TimeUnit.SECONDS);

// Construct the query
Query query = db.collection("cities").orderBy("population").startAt(snapshot);
Python
doc_ref = db.collection(u'cities').document(u'SF')

snapshot = doc_ref.get()
start_at_snapshot = db.collection(
    u'cities').order_by(u'population').start_at(snapshot)
Python
(asincrono)
doc_ref = db.collection("cities").document("SF")

snapshot = await doc_ref.get()
start_at_snapshot = (
    db.collection("cities").order_by("population").start_at(snapshot)
)
C++
db->Collection("cities").Document("SF").Get().OnCompletion(
    [db](const Future<DocumentSnapshot>& future) {
      if (future.error() == Error::kErrorOk) {
        const DocumentSnapshot& document_snapshot = *future.result();
        Query bigger_than_sf = db->Collection("cities")
                                   .OrderBy("population")
                                   .StartAt({document_snapshot});
        // ...
      }
    });
Node.js
const docRef = db.collection('cities').doc('SF');
const snapshot = await docRef.get();
const startAtSnapshot = db.collection('cities')
  .orderBy('population')
  .startAt(snapshot);

await startAtSnapshot.limit(10).get();
Go
cities := client.Collection("cities")
dsnap, err := cities.Doc("SF").Get(ctx)
if err != nil {
	fmt.Println(err)
}
query := cities.OrderBy("population", firestore.Asc).StartAt(dsnap.Data()["population"]).Documents(ctx)
PHP
$citiesRef = $db->collection('samples/php/cities');
$docRef = $citiesRef->document('SF');
$snapshot = $docRef->snapshot();

$query = $citiesRef
    ->orderBy('population')
    ->startAt($snapshot);
Unity
CollectionReference citiesRef = db.Collection("cities");
DocumentReference docRef = citiesRef.Document("SF");
docRef.GetSnapshotAsync().ContinueWith((snapshotTask) =>
{
    Query query = citiesRef.OrderBy("Population").StartAt(snapshotTask.Result);
});
C#
CollectionReference citiesRef = db.Collection("cities");
DocumentReference docRef = citiesRef.Document("SF");
DocumentSnapshot snapshot = await docRef.GetSnapshotAsync();
Query query = citiesRef.OrderBy("Population").StartAt(snapshot);
Ruby
doc_ref = firestore.doc "#{collection_path}/SF"
snapshot = doc_ref.get
query = cities_ref.order("population").start_at(snapshot)

Impaginare una query

Impagina le query combinando i cursori delle query con il metodo limit(). Ad esempio, utilizza l'ultimo documento di un gruppo come inizio di un cursore per il batch successivo.

Versione web 9

import { collection, query, orderBy, startAfter, limit, getDocs } from "firebase/firestore";

// Query the first page of docs
const first = query(collection(db, "cities"), orderBy("population"), limit(25));
const documentSnapshots = await getDocs(first);

// Get the last visible document
const lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
console.log("last", lastVisible);

// Construct a new query starting at this document,
// get the next 25 cities.
const next = query(collection(db, "cities"),
    orderBy("population"),
    startAfter(lastVisible),
    limit(25));

Versione web 8

var first = db.collection("cities")
        .orderBy("population")
        .limit(25);

return first.get().then((documentSnapshots) => {
  // Get the last visible document
  var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
  console.log("last", lastVisible);

  // Construct a new query starting at this document,
  // get the next 25 cities.
  var next = db.collection("cities")
          .orderBy("population")
          .startAfter(lastVisible)
          .limit(25);
});
Swift
Nota:questo prodotto non è disponibile per i target watchOS e per app clip.
// Construct query for first 25 cities, ordered by population
let first = db.collection("cities")
    .order(by: "population")
    .limit(to: 25)

first.addSnapshotListener { (snapshot, error) in
    guard let snapshot = snapshot else {
        print("Error retreving cities: \(error.debugDescription)")
        return
    }

    guard let lastSnapshot = snapshot.documents.last else {
        // The collection is empty.
        return
    }

    // Construct a new query starting after this document,
    // retrieving the next 25 cities.
    let next = db.collection("cities")
        .order(by: "population")
        .start(afterDocument: lastSnapshot)

    // Use the query for pagination.
    // ...
}
Objective-C
Nota:questo prodotto non è disponibile per i target watchOS e per app clip.
FIRQuery *first = [[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"population"]
    queryLimitedTo:25];
[first addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) {
  if (snapshot == nil) {
    NSLog(@"Error retreiving cities: %@", error);
    return;
  }
  if (snapshot.documents.count == 0) { return; }
  FIRDocumentSnapshot *lastSnapshot = snapshot.documents.lastObject;

  // Construct a new query starting after this document,
  // retreiving the next 25 cities.
  FIRQuery *next = [[[db collectionWithPath:@"cities"]
      queryOrderedByField:@"population"]
      queryStartingAfterDocument:lastSnapshot];
  // Use the query for pagination.
  // ...
}];
Java
Android
// Construct query for first 25 cities, ordered by population
Query first = db.collection("cities")
        .orderBy("population")
        .limit(25);

first.get()
    .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot documentSnapshots) {
            // ...

            // Get the last visible document
            DocumentSnapshot lastVisible = documentSnapshots.getDocuments()
                    .get(documentSnapshots.size() -1);

            // Construct a new query starting at this document,
            // get the next 25 cities.
            Query next = db.collection("cities")
                    .orderBy("population")
                    .startAfter(lastVisible)
                    .limit(25);

            // Use the query for pagination
            // ...
        }
    });
Kotlin+KTX
Android
// Construct query for first 25 cities, ordered by population
val first = db.collection("cities")
        .orderBy("population")
        .limit(25)

first.get()
        .addOnSuccessListener { documentSnapshots ->
            // ...

            // Get the last visible document
            val lastVisible = documentSnapshots.documents[documentSnapshots.size() - 1]

            // Construct a new query starting at this document,
            // get the next 25 cities.
            val next = db.collection("cities")
                    .orderBy("population")
                    .startAfter(lastVisible)
                    .limit(25)

            // Use the query for pagination
            // ...
        }

Freccetto

// Construct query for first 25 cities, ordered by population
final first = db.collection("cities").orderBy("population").limit(25);

first.get().then(
  (documentSnapshots) {
    // Get the last visible document
    final lastVisible = documentSnapshots.docs[documentSnapshots.size - 1];

    // Construct a new query starting at this document,
    // get the next 25 cities.
    final next = db
        .collection("cities")
        .orderBy("population")
        .startAfter([lastVisible]).limit(25);

    // Use the query for pagination
    // ...
  },
  onError: (e) => print("Error completing: $e"),
);
Java
// Construct query for first 25 cities, ordered by population.
CollectionReference cities = db.collection("cities");
Query firstPage = cities.orderBy("population").limit(25);

// Wait for the results of the API call, waiting for a maximum of 30 seconds for a result.
ApiFuture<QuerySnapshot> future = firstPage.get();
List<QueryDocumentSnapshot> docs = future.get(30, TimeUnit.SECONDS).getDocuments();

// Construct query for the next 25 cities.
QueryDocumentSnapshot lastDoc = docs.get(docs.size() - 1);
Query secondPage = cities.orderBy("population").startAfter(lastDoc).limit(25);

future = secondPage.get();
docs = future.get(30, TimeUnit.SECONDS).getDocuments();
Python
cities_ref = db.collection(u'cities')
first_query = cities_ref.order_by(u'population').limit(3)

# Get the last document from the results
docs = first_query.stream()
last_doc = list(docs)[-1]

# Construct a new query starting at this document
# Note: this will not have the desired effect if
# multiple cities have the exact same population value
last_pop = last_doc.to_dict()[u'population']

next_query = (
    cities_ref
    .order_by(u'population')
    .start_after({
        u'population': last_pop
    })
    .limit(3)
)
# Use the query for pagination
# ...
Python
(asincrono)
cities_ref = db.collection("cities")
first_query = cities_ref.order_by("population").limit(3)

# Get the last document from the results
docs = [d async for d in first_query.stream()]
last_doc = list(docs)[-1]

# Construct a new query starting at this document
# Note: this will not have the desired effect if
# multiple cities have the exact same population value
last_pop = last_doc.to_dict()["population"]

next_query = (
    cities_ref.order_by("population").start_after({"population": last_pop}).limit(3)
)
# Use the query for pagination
# ...
C++
// Construct query for first 25 cities, ordered by population
Query first = db->Collection("cities").OrderBy("population").Limit(25);

first.Get().OnCompletion([db](const Future<QuerySnapshot>& future) {
  if (future.error() != Error::kErrorOk) {
    // Handle error...
    return;
  }

  // Get the last visible document
  const QuerySnapshot& document_snapshots = *future.result();
  std::vector<DocumentSnapshot> documents = document_snapshots.documents();
  const DocumentSnapshot& last_visible = documents.back();

  // Construct a new query starting at this document,
  // get the next 25 cities.
  Query next = db->Collection("cities")
                   .OrderBy("population")
                   .StartAfter(last_visible)
                   .Limit(25);

  // Use the query for pagination
  // ...
});
Node.js
const first = db.collection('cities')
  .orderBy('population')
  .limit(3);

const snapshot = await first.get();

// Get the last document
const last = snapshot.docs[snapshot.docs.length - 1];

// Construct a new query starting at this document.
// Note: this will not have the desired effect if multiple
// cities have the exact same population value.
const next = db.collection('cities')
  .orderBy('population')
  .startAfter(last.data().population)
  .limit(3);

// Use the query for pagination
// ...
Go
cities := client.Collection("cities")

// Get the first 25 cities, ordered by population.
firstPage := cities.OrderBy("population", firestore.Asc).Limit(25).Documents(ctx)
docs, err := firstPage.GetAll()
if err != nil {
	return err
}

// Get the last document.
lastDoc := docs[len(docs)-1]

// Construct a new query to get the next 25 cities.
secondPage := cities.OrderBy("population", firestore.Asc).
	StartAfter(lastDoc.Data()["population"]).
	Limit(25)

// ...
PHP
$citiesRef = $db->collection('samples/php/cities');
$firstQuery = $citiesRef->orderBy('population')->limit(3);

# Get the last document from the results
$documents = $firstQuery->documents();
$lastPopulation = 0;
foreach ($documents as $document) {
    $lastPopulation = $document['population'];
}

# Construct a new query starting at this document
# Note: this will not have the desired effect if multiple cities have the exact same population value
$nextQuery = $citiesRef->orderBy('population')->startAfter([$lastPopulation]);
$snapshot = $nextQuery->documents();
Unity
CollectionReference citiesRef = db.Collection("cities");
Query firstQuery = citiesRef.OrderBy("Population").Limit(3);

// Get the last document from the results
firstQuery.GetSnapshotAsync().ContinueWith((querySnapshotTask) =>
{
    long lastPopulation = 0;
    foreach (DocumentSnapshot documentSnapshot in querySnapshotTask.Result.Documents)
    {
        lastPopulation = documentSnapshot.GetValue<long>("Population");
    }

    // Construct a new query starting at this document.
    // Note: this will not have the desired effect if multiple cities have the exact same population value
    Query secondQuery = citiesRef.OrderBy("Population").StartAfter(lastPopulation);
    Task<QuerySnapshot> secondQuerySnapshot = secondQuery.GetSnapshotAsync();
C#
CollectionReference citiesRef = db.Collection("cities");
Query firstQuery = citiesRef.OrderBy("Population").Limit(3);

// Get the last document from the results
QuerySnapshot querySnapshot = await firstQuery.GetSnapshotAsync();
long lastPopulation = 0;
foreach (DocumentSnapshot documentSnapshot in querySnapshot.Documents)
{
    lastPopulation = documentSnapshot.GetValue<long>("Population");
}

// Construct a new query starting at this document.
// Note: this will not have the desired effect if multiple cities have the exact same population value
Query secondQuery = citiesRef.OrderBy("Population").StartAfter(lastPopulation);
QuerySnapshot secondQuerySnapshot = await secondQuery.GetSnapshotAsync();
Ruby
cities_ref  = firestore.col collection_path
first_query = cities_ref.order("population").limit(3)

# Get the last document from the results.
last_population = 0
first_query.get do |city|
  last_population = city.data[:population]
end

# Construct a new query starting at this document.
# Note: this will not have the desired effect if multiple cities have the exact same population value.
second_query = cities_ref.order("population").start_after(last_population)
second_query.get do |city|
  puts "Document #{city.document_id} returned by paginated query cursor."
end

Imposta il cursore in base a più campi

Quando utilizzi un cursore basato su un valore di campo (non un DocumentSnapshot), puoi rendere la posizione del cursore più precisa aggiungendo campi aggiuntivi. Ciò è particolarmente utile se il set di dati include più documenti che hanno tutti lo stesso valore per il campo del cursore, rendendo la posizione del cursore ambigua. Puoi aggiungere valori di campo aggiuntivi al cursore per specificare ulteriormente il punto di partenza o di arrivo e ridurre le ambiguità.

Ad esempio, in un set di dati contenente tutte le città denominate "Springfield". Negli Stati Uniti, ci saranno più punti di partenza per l'avvio di una query da "Springfield".

Città
Nome Stato
Springfield Massachusetts
Springfield Missouri
Springfield Wisconsin

Per iniziare da uno Springfield specifico, puoi aggiungere lo stato come condizione secondaria nella clausola del cursore.

Versione web 9

// Will return all Springfields
import { collection, query, orderBy, startAt } from "firebase/firestore";
const q1 = query(collection(db, "cities"),
   orderBy("name"),
   orderBy("state"),
   startAt("Springfield"));

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
const q2 = query(collection(db, "cities"),
   orderBy("name"),
   orderBy("state"),
   startAt("Springfield", "Missouri"));

Versione web 8

// Will return all Springfields
db.collection("cities")
   .orderBy("name")
   .orderBy("state")
   .startAt("Springfield");

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
db.collection("cities")
   .orderBy("name")
   .orderBy("state")
   .startAt("Springfield", "Missouri");
Swift
Nota:questo prodotto non è disponibile per i target watchOS e per app clip.
// Will return all Springfields
db.collection("cities")
    .order(by: "name")
    .order(by: "state")
    .start(at: ["Springfield"])

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
db.collection("cities")
    .order(by: "name")
    .order(by: "state")
    .start(at: ["Springfield", "Missouri"])
Objective-C
Nota: questo prodotto non è disponibile per i target watchOS e per app clip.
// Will return all Springfields
[[[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"name"]
    queryOrderedByField:@"state"]
    queryStartingAtValues:@[ @"Springfield" ]];
// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
[[[[db collectionWithPath:@"cities"]
   queryOrderedByField:@"name"]
   queryOrderedByField:@"state"]
   queryStartingAtValues:@[ @"Springfield", @"Missouri" ]];
Java
Android
// Will return all Springfields
db.collection("cities")
        .orderBy("name")
        .orderBy("state")
        .startAt("Springfield");

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
db.collection("cities")
        .orderBy("name")
        .orderBy("state")
        .startAt("Springfield", "Missouri");
Kotlin+KTX
Android
// Will return all Springfields
db.collection("cities")
        .orderBy("name")
        .orderBy("state")
        .startAt("Springfield")

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
db.collection("cities")
        .orderBy("name")
        .orderBy("state")
        .startAt("Springfield", "Missouri")

Freccetto

// Will return all Springfields
db
    .collection("cities")
    .orderBy("name")
    .orderBy("state")
    .startAt(["Springfield"]);

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
db
    .collection("cities")
    .orderBy("name")
    .orderBy("state")
    .startAt(["Springfield", "Missouri"]);
Java
// Will return all Springfields
Query query1 = db.collection("cities").orderBy("name").orderBy("state").startAt("Springfield");

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
Query query2 =
    db.collection("cities").orderBy("name").orderBy("state").startAt("Springfield", "Missouri");
Python
start_at_name = (
    db.collection(u'cities')
    .order_by(u'name')
    .start_at({
        u'name': u'Springfield'
    })
)

start_at_name_and_state = (
    db.collection(u'cities')
    .order_by(u'name')
    .order_by(u'state')
    .start_at({
        u'name': u'Springfield',
        u'state': u'Missouri'
    })
)
Python
(asincrono)
start_at_name = (
    db.collection("cities")
    .order_by("name")
    .order_by("state")
    .start_at({"name": "Springfield"})
)

start_at_name_and_state = (
    db.collection("cities")
    .order_by("name")
    .order_by("state")
    .start_at({"name": "Springfield", "state": "Missouri"})
)
C++
// This is not yet supported.
Node.js
// Will return all Springfields
const startAtNameRes = await db.collection('cities')
  .orderBy('name')
  .orderBy('state')
  .startAt('Springfield')
  .get();

// Will return 'Springfield, Missouri' and 'Springfield, Wisconsin'
const startAtNameAndStateRes = await db.collection('cities')
  .orderBy('name')
  .orderBy('state')
  .startAt('Springfield', 'Missouri')
  .get();
Go
// Will return all Springfields.
client.Collection("cities").
	OrderBy("name", firestore.Asc).
	OrderBy("state", firestore.Asc).
	StartAt("Springfield")

// Will return Springfields where state comes after Wisconsin.
client.Collection("cities").
	OrderBy("name", firestore.Asc).
	OrderBy("state", firestore.Asc).
	StartAt("Springfield", "Wisconsin")
PHP
// Will return all Springfields
$query1 = $db
    ->collection('samples/php/cities')
    ->orderBy('name')
    ->orderBy('state')
    ->startAt(['Springfield']);

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
$query2 = $db
    ->collection('samples/php/cities')
    ->orderBy('name')
    ->orderBy('state')
    ->startAt(['Springfield', 'Missouri']);
Unity
Query query1 = db.Collection("cities").OrderBy("Name").OrderBy("State").StartAt("Springfield");
Query query2 = db.Collection("cities").OrderBy("Name").OrderBy("State").StartAt("Springfield", "Missouri");
C#
Query query1 = db.Collection("cities").OrderBy("Name").OrderBy("State").StartAt("Springfield");
Query query2 = db.Collection("cities").OrderBy("Name").OrderBy("State").StartAt("Springfield", "Missouri");
Ruby
# Will return all Springfields
query1 = firestore.col(collection_path).order("name").order("state").start_at("Springfield")

# Will return "Springfield, Missouri" and "Springfield, Wisconsin"
query2 = firestore.col(collection_path).order("name").order("state").start_at(["Springfield", "Missouri"])