สรุปข้อมูลด้วยการค้นหาการรวม

การค้นหาการรวมจะประมวลผลข้อมูลจากรายการดัชนีหลายรายการเพื่อแสดงผลค่าสรุปรายการเดียว

Cloud Firestore รองรับการค้นหาการรวมข้อมูลต่อไปนี้

  • count()
  • sum()
  • average()

Cloud Firestore จะคํานวณการรวมและส่งเฉพาะผลลัพธ์กลับไปยังแอปพลิเคชัน การค้นหาการรวมข้อมูลจะประหยัดทั้งการอ่านเอกสารที่เรียกเก็บเงินและจำนวนไบต์ที่โอนได้เมื่อเทียบกับการดำเนินการค้นหาแบบเต็มและการคำนวณการรวมข้อมูลในแอป

การค้นหาการรวมใช้การกำหนดค่าดัชนีที่มีอยู่ซึ่งการค้นหาของคุณใช้อยู่แล้ว และปรับขนาดตามสัดส่วนกับจํานวนรายการดัชนีที่สแกน เวลาในการตอบสนองจะเพิ่มขึ้นตามจํานวนรายการในการรวม

ใช้การรวม count()

คําค้นหาการรวม count() ช่วยให้คุณระบุจํานวนเอกสารในคอลเล็กชันหรือการค้นหาได้

ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลตัวอย่างได้ที่การรับข้อมูล

การรวม count() ต่อไปนี้จะแสดงจํานวนเมืองทั้งหมดในคอลเล็กชัน cities

Web

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities")
let countQuery = query.count
do {
  let snapshot = try await countQuery.getAggregation(source: .server)
  print(snapshot.count)
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRCollectionReference *query = [self.db collectionWithPath:@"cities"];
[query.count aggregationWithSource:FIRAggregateSourceServer
                        completion:^(FIRAggregateQuerySnapshot *snapshot,
                                     NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching count: %@", error);
    } else {
        NSLog(@"Cities count: %@", snapshot.count);
    }
}];

Java

Query query = db.collection("cities");
AggregateQuery countQuery = query.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Count fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Count: " + snapshot.getCount());
        } else {
            Log.d(TAG, "Count failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities")
val countQuery = query.count()
countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Count fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Count: ${snapshot.count}")
    } else {
        Log.d(TAG, "Count failed: ", task.getException())
    }
}

Dart

// Returns number of documents in users collection
db.collection("cities").count().get().then(
      (res) => print(res.count),
      onError: (e) => print("Error completing: $e"),
    );
Go
package firestore

import (
	"context"
	"errors"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
	firestorepb "cloud.google.com/go/firestore/apiv1/firestorepb"
)

func createCountQuery(w io.Writer, projectID string) error {

	// Instantiate the client
	ctx := context.Background()
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return err
	}
	defer client.Close()

	collection := client.Collection("users")
	query := collection.Where("born", ">", 1850)

	// `alias` argument--"all"--provides a key for accessing the aggregate query
	// results. The alias value must be unique across all aggregation aliases in
	// an aggregation query and must conform to allowed Document field names.
	//
	// See https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#document for details.
	aggregationQuery := query.NewAggregationQuery().WithCount("all")
	results, err := aggregationQuery.Get(ctx)
	if err != nil {
		return err
	}

	count, ok := results["all"]
	if !ok {
		return errors.New("firestore: couldn't get alias for COUNT from results")
	}

	countValue := count.(*firestorepb.Value)
	fmt.Fprintf(w, "Number of results from query: %d\n", countValue.GetIntegerValue())
	return nil
}
Java
CollectionReference collection = db.collection("cities");
AggregateQuerySnapshot snapshot = collection.count().get().get();
System.out.println("Count: " + snapshot.getCount());
      
Node.js
const collectionRef = db.collection('cities');
const snapshot = await collectionRef.count().get();
console.log(snapshot.data().count);
      
Python
from google.cloud import firestore
from google.cloud.firestore_v1 import aggregation
from google.cloud.firestore_v1.base_query import FieldFilter


def create_count_query(project_id: str) -> None:
    """Builds an aggregate query that returns the number of results in the query.

    Arguments:
      project_id: your Google Cloud Project ID
    """
    client = firestore.Client(project=project_id)

    collection_ref = client.collection("users")
    query = collection_ref.where(filter=FieldFilter("born", ">", 1800))
    aggregate_query = aggregation.AggregationQuery(query)

    # `alias` to provides a key for accessing the aggregate query results
    aggregate_query.count(alias="all")

    results = aggregate_query.get()
    for result in results:
        print(f"Alias of results from query: {result[0].alias}")
        print(f"Number of results from query: {result[0].value}")

การรวม count() จะพิจารณาตัวกรองในคําค้นหาและประโยค limit

Web

const coll = collection(db, "cities");
const q = query(coll, where("state", "==", "CA"));
const snapshot = await getCountFromServer(q);
console.log('count: ', snapshot.data().count);
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities").whereField("state", isEqualTo: "CA")
let countQuery = query.count
do {
  let snapshot = try await countQuery.getAggregation(source: .server)
  print(snapshot.count)
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query =
    [[self.db collectionWithPath:@"cities"]
                 queryWhereField:@"state"
                       isEqualTo:@"CA"];
[query.count aggregationWithSource:FIRAggregateSourceServer
                        completion:^(FIRAggregateQuerySnapshot *snapshot,
                                      NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching count: %@", error);
    } else {
        NSLog(@"Cities count: %@", snapshot.count);
    }
}];

Java

Query query = db.collection("cities").whereEqualTo("state", "CA");
AggregateQuery countQuery = query.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Count fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Count: " + snapshot.getCount());
        } else {
            Log.d(TAG, "Count failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities").whereEqualTo("state", "CA")
val countQuery = query.count()
countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Count fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Count: ${snapshot.count}")
    } else {
        Log.d(TAG, "Count failed: ", task.getException())
    }
}

Dart

// This also works with collection queries.
db.collection("cities").where("capital", isEqualTo: 10).count().get().then(
      (res) => print(res.count),
      onError: (e) => print("Error completing: $e"),
    );
Go
package firestore

import (
	"context"
	"errors"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
	firestorepb "cloud.google.com/go/firestore/apiv1/firestorepb"
)

func createCountQuery(w io.Writer, projectID string) error {

	// Instantiate the client
	ctx := context.Background()
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return err
	}
	defer client.Close()

	collection := client.Collection("users")
	query := collection.Where("born", ">", 1850)

	// `alias` argument--"all"--provides a key for accessing the aggregate query
	// results. The alias value must be unique across all aggregation aliases in
	// an aggregation query and must conform to allowed Document field names.
	//
	// See https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#document for details.
	aggregationQuery := query.NewAggregationQuery().WithCount("all")
	results, err := aggregationQuery.Get(ctx)
	if err != nil {
		return err
	}

	count, ok := results["all"]
	if !ok {
		return errors.New("firestore: couldn't get alias for COUNT from results")
	}

	countValue := count.(*firestorepb.Value)
	fmt.Fprintf(w, "Number of results from query: %d\n", countValue.GetIntegerValue())
	return nil
}
Java
CollectionReference collection = db.collection("cities");
Query query = collection.whereEqualTo("state", "CA");
AggregateQuerySnapshot snapshot = query.count().get().get();
System.out.println("Count: " + snapshot.getCount());
      
Node.js
const collectionRef = db.collection('cities');
const query = collectionRef.where('state', '==', 'CA');
const snapshot = await query.count().get();
console.log(snapshot.data().count);
      
Python
from google.cloud import firestore
from google.cloud.firestore_v1 import aggregation
from google.cloud.firestore_v1.base_query import FieldFilter


def create_count_query(project_id: str) -> None:
    """Builds an aggregate query that returns the number of results in the query.

    Arguments:
      project_id: your Google Cloud Project ID
    """
    client = firestore.Client(project=project_id)

    collection_ref = client.collection("users")
    query = collection_ref.where(filter=FieldFilter("born", ">", 1800))
    aggregate_query = aggregation.AggregationQuery(query)

    # `alias` to provides a key for accessing the aggregate query results
    aggregate_query.count(alias="all")

    results = aggregate_query.get()
    for result in results:
        print(f"Alias of results from query: {result[0].alias}")
        print(f"Number of results from query: {result[0].value}")

ใช้การรวม sum()

ใช้การรวม sum() เพื่อแสดงผลรวมของค่าตัวเลขทั้งหมดที่ตรงกับข้อความค้นหาที่ระบุ เช่น

Web

const coll = collection(firestore, 'cities');
const snapshot = await getAggregateFromServer(coll, {
  totalPopulation: sum('population')
});

console.log('totalPopulation: ', snapshot.data().totalPopulation);
    
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities")
let aggregateQuery = query.aggregate([AggregateField.sum("population")])
do {
  let snapshot = try await aggregateQuery.getAggregation(source: .server)
  print(snapshot.get(AggregateField.sum("population")))
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query = [self.db collectionWithPath:@"cities"];
FIRAggregateQuery *aggregateQuery = [query aggregate:@[
    [FIRAggregateField aggregateFieldForSumOfField:@"population"]]];
[aggregateQuery aggregationWithSource:FIRAggregateSourceServer
                           completion:^(FIRAggregateQuerySnapshot *snapshot,
                                        NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching aggregate: %@", error);
    } else {
        NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
    }
}];

Java

Query query = db.collection("cities");
AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population"));
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Aggregate fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population")));
        } else {
            Log.d(TAG, "Aggregation failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities")
val aggregateQuery = query.aggregate(AggregateField.sum("population"))
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Aggregate fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}")
    } else {
        Log.d(TAG, "Aggregate failed: ", task.getException())
    }
}

Dart

db.collection("cities").aggregate(sum("population")).get().then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );
Java
collection = db.collection("cities");
snapshot = collection.aggregate(sum("population")).get().get();
System.out.println("Sum: " + snapshot.get(sum("population")));
      
Node.js
const coll = firestore.collection('cities');
const sumAggregateQuery = coll.aggregate({
         totalPopulation: AggregateField.sum('population'),
       });

const snapshot = await sumAggregateQuery.get();
console.log('totalPopulation: ', snapshot.data().totalPopulation);
      
Python
collection_ref = client.collection("users")
aggregate_query = aggregation.AggregationQuery(collection_ref)

aggregate_query.sum("coins", alias="sum")

results = aggregate_query.get()
for result in results:
    print(f"Alias of results from query: {result[0].alias}")
    print(f"Sum of results from query: {result[0].value}")
      
Go
func createSumQuery(w io.Writer, projectID string) error {
  ctx := context.Background()
  client, err := firestore.NewClient(ctx, projectID)
  if err != nil {
    return err
  }
  defer client.Close()

  collection := client.Collection("users")
  query := collection.Where("born", ">", 1850)

  aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins")
  results, err := aggregationQuery.Get(ctx)
  if err != nil {
    return err
  }

  sum, ok := results["sum_coins"]
  if !ok {
    return errors.New("firestore: couldn't get alias for SUM from results")
  }

  sumValue := sum.(*firestorepb.Value)
  fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue())
  return nil
}
      

การรวม sum() จะพิจารณาตัวกรองในข้อความค้นหาและเงื่อไข LIMIT ทั้งหมด เช่น

Web

const coll = collection(firestore, 'cities');
const q = query(coll, where('capital', '==', true));
const snapshot = await getAggregateFromServer(q, {
  totalPopulation: sum('population')
});

console.log('totalPopulation: ', snapshot.data().totalPopulation);
      
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities").whereField("capital", isEqualTo: true)
let aggregateQuery = query.aggregate([AggregateField.sum("population")])
do {
  let snapshot = try await aggregateQuery.getAggregation(source: .server)
  print(snapshot.get(AggregateField.sum("population")))
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query = [[self.db collectionWithPath:@"cities"]
                   queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]];
FIRAggregateQuery *aggregateQuery = [query aggregate:@[
    [FIRAggregateField aggregateFieldForSumOfField:@"population"]]];
[aggregateQuery aggregationWithSource:FIRAggregateSourceServer
                           completion:^(FIRAggregateQuerySnapshot *snapshot,
                                        NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching aggregate: %@", error);
    } else {
        NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
    }
}];

Java

Query query = db.collection("cities").whereEqualTo("capital", true);
AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population"));
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Aggregate fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population")));
        } else {
            Log.d(TAG, "Aggregation failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities").whereEqualTo("capital", true)
val aggregateQuery = query.aggregate(AggregateField.sum("population"))
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Aggregate fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}")
    } else {
        Log.d(TAG, "Aggregate failed: ", task.getException())
    }
}

Dart

db
    .collection("cities")
    .where("capital", isEqualTo: true)
    .aggregate(sum("population"))
    .get()
    .then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );
Java
collection = db.collection("cities");
query = collection.whereEqualTo("state", "CA");
snapshot = query.aggregate(sum("population")).get().get();
System.out.println("Sum: " + snapshot.get(sum("population")));
      
Node.js
const coll = firestore.collection('cities');
const q = coll.where("capital", "==", true);
const sumAggregateQuery = q.aggregate({
        totalPopulation: AggregateField.sum('population'),
      });

const snapshot = await sumAggregateQuery.get();
console.log('totalPopulation: ', snapshot.data().totalPopulation);
      
Python
collection_ref = client.collection("users")
query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew"))
aggregate_query = aggregation.AggregationQuery(query)

aggregate_query.sum("coins", alias="sum")

results = aggregate_query.get()
for result in results:
    print(f"Alias of results from query: {result[0].alias}")
    print(f"Sum of results from query: {result[0].value}")
      
Go
func createSumQuery(w io.Writer, projectID string) error {
  ctx := context.Background()
  client, err := firestore.NewClient(ctx, projectID)
  if err != nil {
    return err
  }
  defer client.Close()

  collection := client.Collection("users")
  query := collection.Where("born", ">", 1850).Limit(5)

  aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins")
  results, err := aggregationQuery.Get(ctx)
  if err != nil {
    return err
  }

  sum, ok := results["sum_coins"]
  if !ok {
    return errors.New("firestore: couldn't get alias for SUM from results")
  }

  sumValue := sum.(*firestorepb.Value)
  fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue())
  return nil
}
      

ใช้การรวม average()

ใช้การรวม average() เพื่อแสดงผลค่าเฉลี่ยของค่าตัวเลขที่ตรงกับข้อความค้นหาที่ระบุ เช่น

Web

const coll = collection(firestore, 'cities');
const snapshot = await getAggregateFromServer(coll, {
  averagePopulation: average('population')
});

console.log('averagePopulation: ', snapshot.data().averagePopulation);
    
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities")
let aggregateQuery = query.aggregate([AggregateField.average("population")])
do {
  let snapshot = try await aggregateQuery.getAggregation(source: .server)
  print(snapshot.get(AggregateField.average("population")))
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query = [self.db collectionWithPath:@"cities"];
FIRAggregateQuery *aggregateQuery = [query aggregate:@[
    [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
[aggregateQuery aggregationWithSource:FIRAggregateSourceServer
                           completion:^(FIRAggregateQuerySnapshot *snapshot,
                                        NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching aggregate: %@", error);
    } else {
        NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
    }
}];

Java

Query query = db.collection("cities");
AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population"));
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Aggregate fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population")));
        } else {
            Log.d(TAG, "Aggregation failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities")
val aggregateQuery = query.aggregate(AggregateField.average("population"))
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Aggregate fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}")
    } else {
        Log.d(TAG, "Aggregate failed: ", task.getException())
    }
}

Dart

db.collection("cities").aggregate(average("population")).get().then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );
Java
collection = db.collection("cities");
snapshot = collection.aggregate(average("population")).get().get();
System.out.println("Average: " + snapshot.get(average("population")));
      
Node.js
const coll = firestore.collection('cities');
const averageAggregateQuery = coll.aggregate({
        averagePopulation: AggregateField.average('population'),
      });

const snapshot = await averageAggregateQuery.get();
console.log('averagePopulation: ', snapshot.data().averagePopulation);
      
Python
collection_ref = client.collection("users")
aggregate_query = aggregation.AggregationQuery(collection_ref)

aggregate_query.avg("coins", alias="avg")

results = aggregate_query.get()
for result in results:
    print(f"Alias of results from query: {result[0].alias}")
    print(f"Average of results from query: {result[0].value}")
      
Go
func createAvgQuery(w io.Writer, projectID string) error {
  ctx := context.Background()
  client, err := firestore.NewClient(ctx, projectID)
  if err != nil {
          return err
  }
  defer client.Close()

  collection := client.Collection("users")
  query := collection.Where("born", ">", 1850)

  aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins")
  results, err := aggregationQuery.Get(ctx)
  if err != nil {
    return err
  }

  avg, ok := results["avg_coins"]
  if !ok {
    return errors.New("firestore: couldn't get alias for AVG from results")
  }

  avgValue := avg.(*firestorepb.Value)
  fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue())
  return nil
}
      

การรวม average() จะพิจารณาตัวกรองในคําค้นหาและอนุประโยคการจำกัด เช่น

Web

const coll = collection(firestore, 'cities');
const q = query(coll, where('capital', '==', true));
const snapshot = await getAggregateFromServer(q, {
  averagePopulation: average('population')
});

console.log('averagePopulation: ', snapshot.data().averagePopulation);
      
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities").whereField("capital", isEqualTo: true)
let aggregateQuery = query.aggregate([AggregateField.average("population")])
do {
  let snapshot = try await aggregateQuery.getAggregation(source: .server)
  print(snapshot.get(AggregateField.average("population")))
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query = [[self.db collectionWithPath:@"cities"]
                   queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]];
FIRAggregateQuery *aggregateQuery = [query aggregate:@[
    [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
[aggregateQuery aggregationWithSource:FIRAggregateSourceServer
                           completion:^(FIRAggregateQuerySnapshot *snapshot,
                                        NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching aggregate: %@", error);
    } else {
        NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
    }
}];

Java

Query query = db.collection("cities").whereEqualTo("capital", true);
AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population"));
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Aggregate fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population")));
        } else {
            Log.d(TAG, "Aggregation failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities").whereEqualTo("capital", true)
val aggregateQuery = query.aggregate(AggregateField.average("population"))
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Aggregate fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}")
    } else {
        Log.d(TAG, "Aggregate failed: ", task.getException())
    }
}

Dart

db
    .collection("cities")
    .where("capital", isEqualTo: true)
    .aggregate(average("population"))
    .get()
    .then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );
Java
collection = db.collection("cities");
query = collection.whereEqualTo("state", "CA");
snapshot = query.aggregate(average("population")).get().get();
System.out.println("Average: " + snapshot.get(average("population")));
  
Node.js
const coll = firestore.collection('cities');
const q = coll.where("capital", "==", true);
const averageAggregateQuery = q.aggregate({
        averagePopulation: AggregateField.average('population'),
      });

const snapshot = await averageAggregateQuery.get();
console.log('averagePopulation: ', snapshot.data().averagePopulation);
      
Python
collection_ref = client.collection("users")
query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew"))
aggregate_query = aggregation.AggregationQuery(query)

aggregate_query.avg("coins", alias="avg")

results = aggregate_query.get()
for result in results:
    print(f"Alias of results from query: {result[0].alias}")
    print(f"Average of results from query: {result[0].value}")
      
Go
func createAvgQuery(w io.Writer, projectID string) error {
  ctx := context.Background()
  client, err := firestore.NewClient(ctx, projectID)
  if err != nil {
        return err
  }
  defer client.Close()

  collection := client.Collection("users")
  query := collection.Where("born", ">", 1850).Limit(5)

  aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins")
  results, err := aggregationQuery.Get(ctx)
  if err != nil {
    return err
  }

  avg, ok := results["avg_coins"]
  if !ok {
    return errors.New("firestore: couldn't get alias for AVG from results")
  }

  avgValue := avg.(*firestorepb.Value)
  fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue())
  return nil
}
      

คํานวณการรวมหลายรายการในการค้นหา

คุณรวมการรวมหลายรายการไว้ในไปป์ไลน์การรวมเดียวได้ ซึ่งจะช่วยลดจํานวนการอ่านดัชนีที่จําเป็น หากการค้นหามีการรวมข้อมูลในหลายช่อง การค้นหาอาจต้องใช้ดัชนีผสม ในกรณีนี้ Cloud Firestore จะแนะนำดัชนี

ตัวอย่างต่อไปนี้จะทําการรวมหลายรายการในการค้นหาการรวมเพียงรายการเดียว

Web

const coll = collection(firestore, 'cities');
const snapshot = await getAggregateFromServer(coll, {
  countOfDocs: count(),
  totalPopulation: sum('population'),
  averagePopulation: average('population')
});

console.log('countOfDocs: ', snapshot.data().countOfDocs);
console.log('totalPopulation: ', snapshot.data().totalPopulation);
console.log('averagePopulation: ', snapshot.data().averagePopulation);
      
Swift
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
let query = db.collection("cities")
let aggregateQuery = query.aggregate([
  AggregateField.count(),
  AggregateField.sum("population"),
  AggregateField.average("population")])
do {
  let snapshot = try await aggregateQuery.getAggregation(source: .server)
  print("Count: \(snapshot.get(AggregateField.count()))")
  print("Sum: \(snapshot.get(AggregateField.sum("population")))")
  print("Average: \(snapshot.get(AggregateField.average("population")))")
} catch {
  print(error)
}
Objective-C
หมายเหตุ: ผลิตภัณฑ์นี้ไม่พร้อมใช้งานบนเป้าหมาย watchOS และ App Clip
FIRQuery *query = [self.db collectionWithPath:@"cities"];
FIRAggregateQuery *aggregateQuery = [query aggregate:@[
    [FIRAggregateField aggregateFieldForCount],
    [FIRAggregateField aggregateFieldForSumOfField:@"population"],
    [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]];
[aggregateQuery aggregationWithSource:FIRAggregateSourceServer
                           completion:^(FIRAggregateQuerySnapshot *snapshot,
                                        NSError *error) {
    if (error != nil) {
        NSLog(@"Error fetching aggregate: %@", error);
    } else {
        NSLog(@"Count: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]]);
        NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]);
        NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]);
    }
}];

Java

Query query = db.collection("cities");
AggregateQuery aggregateQuery = query.aggregate(
        AggregateField.count(),
        AggregateField.sum("population"),
        AggregateField.average("population"));
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) {
        if (task.isSuccessful()) {
            // Aggregate fetched successfully
            AggregateQuerySnapshot snapshot = task.getResult();
            Log.d(TAG, "Count: " + snapshot.get(AggregateField.count()));
            Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population")));
            Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population")));
        } else {
            Log.d(TAG, "Aggregation failed: ", task.getException());
        }
    }
});

Kotlin

val query = db.collection("cities")
val aggregateQuery = query.aggregate(
    AggregateField.count(),
    AggregateField.sum("population"),
    AggregateField.average("population")
)
aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Aggregate fetched successfully
        val snapshot = task.result
        Log.d(TAG, "Count: ${snapshot.get(AggregateField.count())}")
        Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}")
        Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}")
    } else {
        Log.d(TAG, "Aggregate failed: ", task.getException())
    }
}

Dart

db
    .collection("cities")
    .aggregate(
      count(),
      sum("population"),
      average("population"),
    )
    .get()
    .then(
  (res) {
    print(res.count);
    print(res.getSum("population"));
    print(res.getAverage("population"));
  },
  onError: (e) => print("Error completing: $e"),
);
Java
collection = db.collection("cities");
query = collection.whereEqualTo("state", "CA");
AggregateQuery aggregateQuery = query.aggregate(count(), sum("population"), average("population"));
snapshot = aggregateQuery.get().get();
System.out.println("Count: " + snapshot.getCount());
System.out.println("Sum: " + snapshot.get(sum("population")));
System.out.println("Average: " + snapshot.get(average("population")));
    
Node.js
const coll = firestore.collection('cities');
const aggregateQuery = coll.aggregate({
    countOfDocs: AggregateField.count(),
    totalPopulation: AggregateField.sum('population'),
    averagePopulation: AggregateField.average('population')
  });

const snapshot = await aggregateQuery.get();
console.log('countOfDocs: ', snapshot.data().countOfDocs);
console.log('totalPopulation: ', snapshot.data().totalPopulation);
console.log('averagePopulation: ', snapshot.data().averagePopulation);
      
Python
collection_ref = client.collection("users")
query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew"))
aggregate_query = aggregation.AggregationQuery(query)

aggregate_query.sum("coins", alias="sum").avg("coins", alias="avg")

results = aggregate_query.get()
for result in results:
    print(f"Alias of results from query: {result[0].alias}")
    print(f"Aggregation of results from query: {result[0].value}")
      
Go
func createMultiAggregationQuery(w io.Writer, projectID string) error {
  ctx := context.Background()
  client, err := firestore.NewClient(ctx, projectID)
  if err != nil {
    return err
  }
  defer client.Close()

  collection := client.Collection("users")
  query := collection.Where("born", ">", 1850)

  aggregationQuery := query.NewAggregationQuery().WithCount("count").WithSum("coins", "sum_coins").WithAvg("coins", "avg_coins")
  results, err := aggregationQuery.Get(ctx)
  if err != nil {
    return err
  }
}
      

การค้นหาที่มีการรวมหลายรายการจะมีเฉพาะเอกสารที่มีช่องทั้งหมดในการรวมแต่ละรายการ ซึ่งอาจทําให้ผลลัพธ์แตกต่างไปจากการรวมแต่ละรายการแยกกัน

กฎความปลอดภัยสําหรับการค้นหาการรวม

Cloud Firestore Security Rules จะทํางานกับคําค้นหาการรวมข้อมูลเช่นเดียวกับคําค้นหาที่แสดงเอกสาร กล่าวคือ ลูกค้าจะทำการรวมข้อมูลในคำค้นหาเหล่านั้นได้ก็ต่อเมื่อกฎของคุณอนุญาตให้ลูกค้าเรียกใช้การค้นหาคอลเล็กชันหรือกลุ่มคอลเล็กชันหนึ่งๆ เท่านั้น ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ Cloud Firestore Security Rules โต้ตอบกับการค้นหา

ลักษณะการทำงานและข้อจำกัด

ขณะทํางานกับคําค้นหาการรวม ให้คํานึงถึงลักษณะการทํางานและข้อจํากัดต่อไปนี้

  • คุณใช้การค้นหาการรวมกับเครื่องมือรับฟังแบบเรียลไทม์และการค้นหาแบบออฟไลน์ไม่ได้ ระบบรองรับการค้นหาการรวมผ่านคําตอบของเซิร์ฟเวอร์โดยตรงเท่านั้น แบ็กเอนด์ Cloud Firestore จะแสดงการค้นหาเท่านั้น โดยจะข้ามแคชในเครื่องและการอัปเดตที่บัฟเฟอร์ไว้ ลักษณะการทํางานนี้เหมือนกับการดำเนินการที่ดำเนินการภายในCloud Firestore ธุรกรรม

  • หากการรวมข้อมูลไม่สามารถแก้ไขได้ภายใน 60 วินาที ระบบจะแสดงข้อผิดพลาด DEADLINE_EXCEEDED ประสิทธิภาพขึ้นอยู่กับการกําหนดค่าดัชนีและขนาดของชุดข้อมูล

    หากดำเนินการไม่เสร็จภายในกำหนดเวลา 60 วินาที วิธีแก้ปัญหาที่เป็นไปได้คือใช้ตัวนับสำหรับชุดข้อมูลขนาดใหญ่

  • การค้นหาการรวมข้อมูลจะอ่านจากรายการดัชนีและรวมเฉพาะช่องที่จัดทําดัชนีเท่านั้น

  • การเพิ่มอนุประโยค OrderBy ลงในคําค้นหาการรวมจะจํากัดการรวมไว้เฉพาะเอกสารที่มีช่องการจัดเรียง

  • สําหรับการรวมข้อมูล sum() และ average() ระบบจะไม่สนใจค่าที่ไม่ใช่ตัวเลข การรวม sum() และ average() จะพิจารณาเฉพาะค่าจำนวนเต็มและค่าตัวเลขทศนิยม

  • เมื่อรวมการรวมหลายรายการไว้ในคําค้นหาเดียว โปรดทราบว่า sum() และ average() จะไม่สนใจค่าที่ไม่ใช่ตัวเลข ขณะที่ count() จะรวมค่าที่ไม่ใช่ตัวเลข

  • หากคุณรวมการรวมที่อยู่ในช่องต่างๆ การคำนวณจะรวมเฉพาะเอกสารที่มีช่องเหล่านั้นทั้งหมด

ราคา

ราคาสำหรับการค้นหาแบบรวมจะขึ้นอยู่กับจํานวนรายการดัชนีที่การค้นหาตรงกัน ระบบจะเรียกเก็บเงินค่าอ่านจำนวนเล็กน้อยสำหรับรายการที่ตรงกันจำนวนมาก ระบบจะเรียกเก็บเงินจากคุณสำหรับการดำเนินการอ่าน 1 ครั้งสำหรับแต่ละกลุ่มที่อ่านรายการดัชนีได้สูงสุด 1,000 รายการ

ดูข้อมูลเพิ่มเติมเกี่ยวกับราคาการค้นหาการรวมได้ที่การค้นหาการรวม