الوصف
تنشئ مستندات جديدة، إما من خلال الإشارة إلى مجموعة فرعية من الحقول الحالية أو من خلال تخصيص حقل لنتيجة تعبير معيّن.
أمثلة
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();
متابعة
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)
السلوك
حقول البيانات الوصفية للمستند
لا تُصدِر مرحلة select(...) سوى الحقول أو التعبيرات المحدّدة صراحةً في المرحلة. يختلف هذا عن عمليات Core حيث يعمل الإعداد select(...) في طلب البحث كقناع للسمات بدلاً من إسقاط، كما أنّه دائمًا يتضمّن حقول البيانات الوصفية للمستند __name__ و__create_time__ و__update_time__.
للحصول على سلوك يشبه عمليات Core في select(...)، يجب تحديد الحقول بشكل صريح، مثل:
Node.js
const results = await db.pipeline()
.collection("/users")
.select(
field("__name__"),
field("__create_time__"),
field("__update_time__"),
field("email"))
.execute();
موضع مرحلة اختيار
لا توجد قيود على وقت استخدام مرحلة الاختيار، ولكن أي حقول غير
مضمنة في مرحلة الاختيار لن تكون متاحة للمراحل اللاحقة في
المسار. على سبيل المثال، لاختيار الحقلين name وlocation فقط لجميع
المدن في كندا من مجموعة البيانات التالية:
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"}
});
يمكن استخدام المسار التالي:
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();
والذي ينتج عنه المستندات التالية:
{ name: "Toronto, Canada", population: 3000000 },
ومع ذلك، إذا تم وضع المرحلة select(...) بدلاً من ذلك قبل المرحلة
where(...)، مثل:
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();
لن يتم إنشاء أي مستندات، لأنّه تمت إزالة location.country من
المستند قبل تنفيذ مرحلة
where(...).
اختيار الحقول المتداخلة
يمكن استخدام مرحلة select(...) لاختيار الحقول المُدمجة من كل من الخرائط والمصفوفات. على سبيل المثال، لاختيار حقل country المُدمج والإدخال الأول لمصفوفة landmarks من المستندات التالية:
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
});
يمكن استخدام المسار التالي:
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();
والذي ينتج عنه المستندات التالية:
{ city: "San Francisco", country: "USA", topLandmark: "Golden Gate Bridge" },
{ city: "Toronto", country: "Canada", topLandmark: "CN Tower" },
{ city: "Atlantis" }
إذا لم تكن قيمة الخريطة أو الصفيف المضمّنة متوفّرة، لن يتم تضمينها في
المستند الناتج. يتطابق سلوك الوصول إلى المصفوفات والخرائط في مرحلة الاختيار
مع الدالتَين offset(...) وget_field(...)
على التوالي.
تخصيص الحقول المدمجة
يمكن أيضًا تعيين نتيجة تعبير إلى حقل مدمج، مما يجعل من الممكن أن تُرجع مرحلة select(...) مجموعة فرعية من الحقول المدمجة من المرحلة السابقة. على سبيل المثال، يمكن استخدام ما يلي لضمان عرض معلومات city وstate فقط مع الحفاظ على الشكل الأصلي للمستند:
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();