Chọn

Mô tả

Tạo tài liệu mới, bằng cách tham chiếu một tập hợp con của các trường hiện có hoặc bằng cách chỉ định một trường cho kết quả của một biểu thức nhất định.

Ví dụ

Web

const result = await execute(db.pipeline()
  .collection("books")
  .select(field("soldBooks").multiply(field("price")).round().as("partialRevenue"))
  .aggregate(field("partialRevenue").sum().as("totalRevenue"))
  );
Swift
let result = try await db.pipeline()
  .collection("books")
  .select([Field("soldBooks").multiply(Field("price")).round().as("partialRevenue")])
  .aggregate([Field("partialRevenue").sum().as("totalRevenue")])
  .execute()

Kotlin

val result = db.pipeline()
    .collection("books")
    .select(Expression.multiply(field("soldBooks"), field("price")).round().alias("partialRevenue"))
    .aggregate(AggregateFunction.sum("partialRevenue").alias("totalRevenue"))
    .execute()

Java

Task<Pipeline.Snapshot> result = db.pipeline()
    .collection("books")
    .select(Expression.multiply(field("soldBooks"), field("price")).round().alias("partialRevenue"))
    .aggregate(AggregateFunction.sum("partialRevenue").alias("totalRevenue"))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

result = (
    client.pipeline()
    .collection("books")
    .select(
        Field.of("soldBooks")
        .multiply(Field.of("price"))
        .round()
        .as_("partialRevenue")
    )
    .aggregate(Field.of("partialRevenue").sum().as_("totalRevenue"))
    .execute()
)
Java
Pipeline.Snapshot result =
    firestore
        .pipeline()
        .collection("books")
        .select(round(multiply(field("soldBooks"), field("price"))).as("partialRevenue"))
        .aggregate(sum("partialRevenue").as("totalRevenue"))
        .execute()
        .get();
Bắt đầu
snapshot := client.Pipeline().
	Collection("books").
	Select(firestore.Fields(
		firestore.Round(firestore.Multiply(firestore.FieldOf("soldBooks"), firestore.FieldOf("price"))).As("partialRevenue"),
	)).
	Aggregate(firestore.Accumulators(
		firestore.Sum("partialRevenue").As("totalRevenue"),
	)).
	Execute(ctx)

Hành vi

Trường siêu dữ liệu của tài liệu

Giai đoạn select(...) chỉ phát ra các trường hoặc biểu thức được chỉ định rõ ràng trong giai đoạn này. Đây là điểm khác biệt so với các thao tác Core, trong đó chế độ cài đặt select(...) trên một truy vấn hoạt động như một mặt nạ thuộc tính thay vì một phép chiếu và luôn bao gồm các trường siêu dữ liệu của tài liệu là __name__, __create_time____update_time__.

Để có được hành vi theo kiểu hoạt động của Core trong select(...), bạn phải chỉ định rõ ràng các trường như:

Node.js

const results = await db.pipeline()
  .collection("/users")
  .select(
    field("__name__"),
    field("__create_time__"),
    field("__update_time__"),
    field("email"))
  .execute();

Vị trí của một giai đoạn chọn

Không có hạn chế về thời điểm có thể sử dụng một giai đoạn chọn, nhưng mọi trường không có trong giai đoạn chọn sẽ không thể truy cập vào các giai đoạn tiếp theo trong quy trình. Ví dụ: để chỉ chọn các trường namelocation của tất cả các thành phố ở Canada trong tập dữ liệu sau:

Node.js

await db.collection("cities").doc("SF").set({
  name: "San Francisco",
  population: 800000,
  location: {country: "USA", state: "California"}
});

await db.collection("cities").doc("TO").set({
  name: "Toronto",
  population: 3000000,
  location: {country: "Canada", province: "Ontario"}
});

Bạn có thể sử dụng quy trình sau:

Node.js

const names = await db.pipeline()
  .collection("/cities")
  .where(equal(field("location.country"), "Canada"))
  .select(stringConcat(field("name"), ", ", field("location.country")).as("name"), "population")
  .execute();

Điều này tạo ra các tài liệu sau:

{ name: "Toronto, Canada", population: 3000000 },

Tuy nhiên, nếu giai đoạn select(...) được đặt trước giai đoạn where(...), chẳng hạn như:

Node.js

const names = await db.pipeline()
  .collection("/cities")
  .select(stringConcat(field("name"), ",", field("location.country")).as("name"), "population")
  .where(equal(field("location.country"), "Canada"))
  .execute();

Không có tài liệu nào được tạo ra vì location.country đã bị xoá khỏi tài liệu trước khi thực thi giai đoạn where(...).

Chọn các trường lồng nhau

Bạn có thể dùng giai đoạn select(...) để chọn các trường lồng ghép từ cả bản đồ và mảng. Ví dụ: để chọn trường country được lồng và mục nhập đầu tiên của mảng landmarks trong các tài liệu sau:

Node.js

await db.collection("cities").doc("SF").set({
  name: "San Francisco",
  population: 800000,
  location: { country: "USA", state: "California" },
  landmarks: [ "Golden Gate Bridge", "Alcatraz" ]
});

await db.collection("cities").doc("TO").set({
  name: "Toronto",
  population:  3000000,
  province: "ON",
  location: { country: "Canada", province: "Ontario" },
  landmarks: [ "CN Tower", "Casa Loma" ]
});

await db.collection("cities").doc("AT").set({
  name: "Atlantis",
  population: null
});

Bạn có thể sử dụng quy trình sau:

Node.js

const locations = await db.pipeline()
  .collection("/cities")
  .select(
    field("name").as("city"),
    field("location.country").as("country"),
    field("landmarks").offset(0).as("topLandmark"))
  .execute();

Điều này tạo ra các tài liệu sau:

{ city: "San Francisco", country: "USA", topLandmark: "Golden Gate Bridge" },
{ city: "Toronto", country: "Canada", topLandmark: "CN Tower" },
{ city: "Atlantis" }

Nếu không có giá trị bản đồ lồng nhau hoặc giá trị mảng, thì giá trị đó sẽ không được đưa vào tài liệu kết quả. Quyền truy cập vào mảng và bản đồ ở giai đoạn chọn hoạt động giống hệt như các hàm offset(...)get_field(...), tương ứng.

Chỉ định các trường lồng nhau

Kết quả của một biểu thức cũng có thể được chỉ định cho một trường lồng nhau, giúp bạn có thể có giai đoạn select(...) trả về một tập hợp con các trường lồng nhau từ giai đoạn trước. Ví dụ: bạn có thể dùng đoạn mã sau để đảm bảo chỉ thông tin citystate được trả về trong khi vẫn giữ nguyên hình dạng ban đầu của tài liệu:

Node.js

const results = await db.pipeline()
  .collection("/users")
  .addFields(
    field("__name__"),
    field("address.city").as("address.city"),
    field("address.state").as("address.state"))
  .execute();