فريد

الوصف

يمكنك العثور على جميع المجموعات المختلفة من القيم لسلسلة من التعبيرات.

تتضمّن مرحلة distinct(...) بنية جملة مشابهة لبنية جملة select(...) لأنّها تأخذ تعبيرًا واحدًا أو أكثر يمكن اختياره. يمكن استخدام السلاسل عندما يكون التعبير مجرّد مرجع حقل:

أمثلة

Node.js
let cities = await db.pipeline()
  .collection("cities")
  .distinct("country")
  .execute();

cities = await db.pipeline()
  .collection("cities")
  .distinct(
    field("state").toLower().as("normalizedState"),
    field("country"))
  .execute();

Web

let cities = await execute(db.pipeline()
  .collection("cities")
  .distinct("country"));

cities = await execute(db.pipeline()
  .collection("cities")
  .distinct(
    field("state").toLower().as("normalizedState"),
    field("country")));
Swift
let results = try await db.pipeline()
  .collection("books")
  .distinct([
    Field("author").toUpper().as("author"),
    Field("genre")
  ])
  .execute()

Kotlin

var cities = db.pipeline()
    .collection("cities")
    .distinct("country")
    .execute()

cities = db.pipeline()
    .collection("cities")
    .distinct(
        field("state").toLower().alias("normalizedState"),
        field("country")
    )
    .execute()

Java

Task<Pipeline.Snapshot> cities;
cities = db.pipeline()
        .collection("cities")
        .distinct("country")
        .execute();

cities = db.pipeline()
        .collection("cities")
        .distinct(
                field("state").toLower().alias("normalizedState"),
                field("country"))
        .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

cities = client.pipeline().collection("cities").distinct("country").execute()

cities = (
    client.pipeline()
    .collection("cities")
    .distinct(Field.of("state").to_lower().as_("normalizedState"), "country")
    .execute()
)
Java
Pipeline.Snapshot cities1 =
    firestore.pipeline().collection("cities").distinct("country").execute().get();

Pipeline.Snapshot cities2 =
    firestore
        .pipeline()
        .collection("cities")
        .distinct(toLower(field("state")).as("normalizedState"), field("country"))
        .execute()
        .get();
Go
cities1, err := client.Pipeline().Collection("cities").Distinct(firestore.Fields("country")).Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

cities2, err := client.Pipeline().Collection("cities").
	Distinct(firestore.Fields(
		firestore.ToLower(firestore.FieldOf("state")).As("normalizedState"),
		firestore.FieldOf("country"),
	)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

السلوك

تعمل مرحلة distinct(...) بطريقة مشابهة لمرحلة aggregate(...) بدون مجموعات. يمكنك الاطّلاع أيضًا على aggregate(...) و select(...).

العثور على قيم الحقول المختلفة

على سبيل المثال، للحصول على قائمة بكل بلد في مجموعة cities التالية:

Node.js

await db.collection("cities").doc("SF").set({name: "San Francisco", state: "CA", country: "USA"});
await db.collection("cities").doc("LA").set({name: "Los Angeles", state: "CA", country: "USA"});
await db.collection("cities").doc("NY").set({name: "New York", state: "NY", country: "USA"});
await db.collection("cities").doc("TOR").set({name: "Toronto", state: null, country: "Canada"});
await db.collection("cities").doc("MEX").set({name: "Mexico City", state: null, country: "Mexico"});

يمكن العثور على البلدان المختلفة باستخدام:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct("country")
  .execute();

ما يؤدي إلى ظهور النتيجة التالية:

{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }

الناتج المختلف للتعبيرات

يمكنك أيضًا العثور على المجموعات المختلفة من حقول متعددة أو تعبيرات أكثر تعقيدًا. على سبيل المثال:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct(
    field("state").toLower().as("normalized_state"),
    field("country"))
  .execute();

للحصول على:

{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }

سلوكيات التكافؤ

يتبع سلوك التكافؤ في القيم المختلفة الدلالات نفسها التي تتبعها المساواة.

يعني ذلك أنّ القيم المتكافئة، على سبيل المثال القيم الرقمية المتكافئة رياضيًا، بغض النظر عن الأنواع الأصلية (عدد صحيح 32 بت، وعدد صحيح 64 بت، وأرقام الفاصلة العائمة، والأرقام العشرية، وما إلى ذلك)، تُعتبر القيمة المختلفة نفسها.

على سبيل المثال، في مجموعة numerics تتضمّن مستندات مختلفة تحتوي على foo قيم من عدد صحيح 32 بت 1 وعدد صحيح 64 بت 1L ورقم الفاصلة العائمة 1.0 على التوالي، لن تعرض distinct(...) سوى نتيجة واحدة.

في هذه الحالات التي تتضمّن قيمًا مختلفة متكافئة في مجموعة البيانات، يمكن أن تكون قيمة الناتج للمجموعة أيًا من هذه القيم المتكافئة. في هذا المثال، يمكن عرض قيمة foo هذه على أنّها 1 أو 1L أو 1.0.

حتى إذا بدا أنّها حتمية، يجب عدم محاولة الاعتماد على سلوك اختيار قيمة معيّنة.

استخدام الذاكرة

تعتمد طريقة تنفيذ مرحلة distinct(...) على الفهارس المتاحة. عندما لا يختار محسِّن طلب البحث فهرسًا مناسبًا، تتطلّب distinct(...) تخزين جميع القيم المختلفة مؤقتًا في الذاكرة.

في حال وجود عدد كبير جدًا من القيم المختلفة أو قيم كبيرة جدًا (على سبيل المثال، قيم مختلفة كبيرة)، قد تنفد الذاكرة في هذه المرحلة.

في هذه الحالات، عليك تطبيق الفلاتر للحدّ من مجموعة البيانات التي سيتم تنفيذ distinct(...) عليها، أو إنشاء فهارس على النحو الموصى به لتجنُّب استخدام الذاكرة بشكل كبير.

ستوفّر ميزة "شرح طلب البحث" معلومات عن خطة تنفيذ طلب البحث الفعلية وبيانات تحديد الملف الشخصي للمساعدة في تصحيح الأخطاء.