Buka konsol

Menomori data dengan Query Cursor

Dengan query cursor di Cloud Firestore, Anda dapat membagi data yang ditampilkan oleh kueri ke dalam batch menurut parameter yang ditetapkan dalam kueri tersebut.

Query cursor menentukan titik awal dan akhir untuk kueri, sehingga Anda dapat:

  • Menampilkan subkumpulan data.
  • Memberi nomor pada hasil kueri.

Namun, untuk menentukan rentang spesifik kueri, Anda harus menggunakan metode where() yang dijelaskan dalam Kueri Sederhana.

Menambahkan kursor sederhana ke kueri

Gunakan metode startAt() atau startAfter() untuk menentukan titik awal kueri. Metode startAt() menyertakan titik awal, sementara metode startAfter() mengecualikannya.

Misalnya, jika Anda menggunakan startAt(A) dalam kueri, kueri akan menampilkan seluruh alfabet. Jika Anda menggunakan startAfter(A), kueri akan menampilkan B-Z.

Web
citiesRef.orderBy("population").startAt(1000000)
Swift
// Get all cities with population over one million, ordered by population.
db.collection("cities")
    .order(by: "population")
    .start(at: [1000000])
Objective-C
// Get all cities with population over one million, ordered by population.
[[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"population"]
    queryStartingAtValues:@[ @1000000 ]];
  
Java
// Get all cities with a population >= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .startAt(1000000);
Kotlin
// Get all cities with a population >= 1,000,000, ordered by population,
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
})
Node.js
let startAt = db.collection('cities')
  .orderBy('population')
  .startAt(1000000);
Go
query := client.Collection("cities").OrderBy("population", firestore.Asc).StartAt(1000000)
PHP
$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)

Demikian pula, gunakan metode endAt() atau endBefore() untuk menentukan titik akhir untuk hasil kueri Anda.

Web
citiesRef.orderBy("population").endAt(1000000)
Swift
// Get all cities with population less than one million, ordered by population.
db.collection("cities")
    .order(by: "population")
    .end(at: [1000000])
Objective-C
// Get all cities with population less than one million, ordered by population.
[[[db collectionWithPath:@"cities"]
    queryOrderedByField:@"population"]
    queryEndingAtValues:@[ @1000000 ]];
  
Java
// Get all cities with a population <= 1,000,000, ordered by population,
db.collection("cities")
        .orderBy("population")
        .endAt(1000000);
Kotlin
// Get all cities with a population <= 1,000,000, ordered by population,
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
})
Node.js
let endAt = db.collection('cities')
  .orderBy('population')
  .endAt(1000000);
Go
query := client.Collection("cities").OrderBy("population", firestore.Asc).EndAt(1000000)
PHP
$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)

Menggunakan snapshot dokumen untuk menentukan query cursor

Anda juga dapat meneruskan snapshot dokumen ke klausa kursor sebagai titik awal atau akhir query cursor. Nilai dalam snapshot dokumen berfungsi sebagai nilai dalam query cursor.

Misalnya, ambil snapshot dokumen "San Francisco" di kumpulan data kota dan populasi. Kemudian, gunakan snapshot dokumen tersebut sebagai titik awal untuk query cursor populasi Anda. Kueri akan menampilkan semua kota berpopulasi lebih tinggi atau sama dengan populasi San Francisco, seperti yang ditentukan dalam snapshot dokumen.

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

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

    // ...
});
Swift
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
[[[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
// 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
// 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)

            // ...
        }
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)
Node.js
let docRef = db.collection('cities').doc('SF');
return docRef.get().then(snapshot => {
  let startAtSnapshot = db.collection('cities')
    .orderBy('population')
    .startAt(snapshot);

  return 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('cities');
$docRef = $citiesRef->document('SF');
$snapshot = $docRef->snapshot();

$query = $citiesRef
    ->orderBy('population')
    ->startAt($snapshot);
C#
CollectionReference citiesRef = db.Collection("cities");
DocumentReference docRef = citiesRef.Document("SF");
DocumentSnapshot snapshot = await docRef.GetSnapshotAsync();
Query query = citiesRef.OrderBy("Population").StartAt(snapshot);
Ruby
// Snippet not available

Memberi nomor pada kueri

Beri nomor pada kueri dengan memadukan query cursor dengan metode limit(). Misalnya, gunakan dokumen terakhir dalam batch sebagai awal kursor untuk batch berikutnya.

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

return first.get().then(function (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
// 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
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
// 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
// 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
            // ...
        }
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
# ...
Node.js
let first = db.collection('cities')
  .orderBy('population')
  .limit(3);

let paginate = first.get()
  .then((snapshot) => {
    // ...

    // Get the last document
    let 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.
    let 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('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();
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 "cities"
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

Menetapkan beberapa condition kursor

Untuk menambahkan perincian ke titik awal atau akhir kursor, Anda dapat menentukan beberapa condition dalam klausa kursor. Hal ini sangat berguna jika kumpulan data Anda mencakup kolom, dengan condition pertama dalam klausa kursor akan menampilkan beberapa hasil. Gunakan beberapa condition untuk menentukan lebih lanjut titik awal dan akhir, serta untuk mengurangi ambiguitas.

Misalnya, dalam kumpulan data yang berisi semua kota bernama "Springfield" di Amerika Serikat, akan ada beberapa titik awal untuk kueri yang ditetapkan untuk dimulai di "Springfield":

Kota
Nama Negara Bagian
Springfield Massachusetts
Springfield Missouri
Springfield Wisconsin

Untuk memulai di Springfield tertentu, Anda dapat menambahkan negara bagian sebagai condition sekunder dalam klausa kursor.

Web
// 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
// 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
// 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
// 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
// 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')
    .order_by(u'state')
    .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'
    })
)
Node.js
// Will return all Springfields
let startAtName = db.collection('cities')
  .orderBy('name')
  .orderBy('state')
  .startAt('Springfield');
// Will return 'Springfield, Missouri' and 'Springfield, Wisconsin'
let startAtNameAndState = db.collection('cities')
  .orderBy('name')
  .orderBy('state')
  .startAt('Springfield', 'Missouri');
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('cities')
    ->orderBy('name')
    ->orderBy('state')
    ->startAt(['Springfield']);

// Will return "Springfield, Missouri" and "Springfield, Wisconsin"
$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("cities").order("name").order("state").start_at("Springfield")

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