Auswählen

Beschreibung

Generiert neue Dokumente, entweder durch Verweisen auf eine Teilmenge vorhandener Felder oder durch Zuweisen eines Felds zum Ergebnis eines bestimmten Ausdrucks.

Beispiele

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();
Go
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)

Verhalten

Dokumentmetadatenfelder

In der Phase select(...) werden nur die Felder oder Ausdrücke ausgegeben, die explizit in der Phase angegeben sind. Dies weicht von den Core-Vorgängen ab, bei denen die Einstellung select(...) für eine Anfrage als Attributmaske und nicht als Projektion fungiert und immer die Metadatenfelder des Dokuments __name__, __create_time__ und __update_time__ enthält.

Damit sich ein select(...) wie bei Core-Vorgängen verhält, müssen die Felder explizit angegeben werden, z. B.:

Node.js

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

Position einer Select Stage

Es gibt keine Einschränkungen hinsichtlich des Zeitpunkts, zu dem eine SELECT-Phase verwendet werden kann. Auf Felder, die nicht in einer SELECT-Phase enthalten sind, kann in nachfolgenden Phasen einer Pipeline nicht zugegriffen werden. Wenn Sie beispielsweise nur die Felder name und location aller Städte in Kanada aus dem folgenden Dataset auswählen möchten:

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"}
});

Die folgende Pipeline kann verwendet werden:

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();

Dadurch werden die folgenden Dokumente erstellt:

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

Wenn die Phase select(...) jedoch vor der Phase where(...) platziert wird, z. B. so:

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();

Es werden keine Dokumente erstellt, da location.country vor der Ausführung der Phase where(...) aus dem Dokument entfernt wurde.

Verschachtelte Felder auswählen

Mit der Phase select(...) können Sie verschachtelte Felder aus Karten und Arrays auswählen. Wenn Sie beispielsweise das verschachtelte Feld country und den ersten Eintrag des Arrays landmarks aus den folgenden Dokumenten auswählen möchten:

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
});

Die folgende Pipeline kann verwendet werden:

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();

Dadurch werden die folgenden Dokumente erstellt:

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

Wenn ein verschachtelter Kartenwert oder Arraywert nicht vorhanden ist, wird er nicht in das resultierende Dokument aufgenommen. Der Array- und Kartenzugriff in der SELECT-Phase verhält sich identisch mit den Funktionen offset(...) bzw. get_field(...).

Verschachtelte Felder zuweisen

Das Ergebnis eines Ausdrucks kann auch einem verschachtelten Feld zugewiesen werden. So kann in der Phase select(...) eine Teilmenge verschachtelter Felder aus der vorherigen Phase zurückgegeben werden. Mit den folgenden Parametern kann beispielsweise dafür gesorgt werden, dass nur die Informationen city und state zurückgegeben werden, während die ursprüngliche Form des Dokuments beibehalten wird:

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();