Firestore Pipeline की कार्रवाइयों की मदद से डेटा पाना

बैकग्राउंड

पाइपलाइन ऑपरेशन, Cloud Firestore के लिए एक नया क्वेरी इंटरफ़ेस उपलब्ध कराते हैं. यह इंटरफ़ेस, बेहतर क्वेरी फ़ंक्शन और जटिल एक्सप्रेशन के साथ काम करता है. इसमें कई नए फ़ंक्शन जोड़े गए हैं. इनमें min(...), max(...), substring(...), regex_match(...), और array_contains_all(...) शामिल हैं. साथ ही, इसमें मुश्किल ट्रांसफ़ॉर्मेशन करने के लिए स्टेज भी जोड़े गए हैं.

शुरू करें

क्लाइंट एसडीके इंस्टॉल और शुरू करने के लिए, इन गाइड में दिए गए निर्देश देखें:

सिंटैक्स

यहां दिए गए सेक्शन में, पाइपलाइन ऑपरेशन के सिंटैक्स के बारे में खास जानकारी दी गई है.

कॉन्सेप्ट

पाइपलाइन ऑपरेशन में एक अहम अंतर यह है कि इसमें "स्टेज" का क्रम साफ़ तौर पर बताया जाता है. इससे ज़्यादा जटिल क्वेरी को बेहतर तरीके से समझा जा सकता है. हालांकि, यह कोर ऑपरेशन का इस्तेमाल करने वाले मौजूदा क्वेरी इंटरफ़ेस से काफ़ी अलग है. इसमें चरणों का क्रम पहले से तय होता था. पाइपलाइन ऑपरेशन का यह उदाहरण देखें:

Web

const pipeline = db.pipeline()
  // Step 1: Start a query with collection scope
  .collection("cities")
  // Step 2: Filter the collection
  .where(field("population").greaterThan(100000))
  // Step 3: Sort the remaining documents
  .sort(field("name").ascending())
  // Step 4: Return the top 10. Note applying the limit earlier in the
  // pipeline would have unintentional results.
  .limit(10);
Swift
let pipeline = db.pipeline()
  // Step 1: Start a query with collection scope
  .collection("cities")
  // Step 2: Filter the collection
  .where(Field("population").greaterThan(100000))
  // Step 3: Sort the remaining documents
  .sort([Field("name").ascending()])
  // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have
  // unintentional results.
  .limit(10)

Kotlin

val pipeline = db.pipeline()
    // Step 1: Start a query with collection scope
    .collection("cities")
    // Step 2: Filter the collection
    .where(field("population").greaterThan(100000))
    // Step 3: Sort the remaining documents
    .sort(field("name").ascending())
    // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have
    // unintentional results.
    .limit(10)

Java

Pipeline pipeline = db.pipeline()
    // Step 1: Start a query with collection scope
    .collection("cities")
    // Step 2: Filter the collection
    .where(field("population").greaterThan(100000))
    // Step 3: Sort the remaining documents
    .sort(field("name").ascending())
    // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have
    // unintentional results.
    .limit(10);
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

pipeline = (
    client.pipeline()
    .collection("cities")
    .where(Field.of("population").greater_than(100_000))
    .sort(Field.of("name").ascending())
    .limit(10)
)
जाएं
pipeline := client.Pipeline().
	Collection("cities").
	Where(firestore.FieldOf("population").GreaterThan(100000)).
	Sort(firestore.Orders(firestore.Ascending(firestore.FieldOf("name")))).
	Limit(10)

डेटा लेयर में इवेंट बनाने की प्रोसेस

पाइपलाइन ऑपरेशन का सिंटैक्स, मौजूदा Cloud Firestore क्वेरी से काफ़ी मिलता-जुलता है. शुरू करने के लिए, यह लिखकर क्वेरी को शुरू करें:

Web

const { getFirestore } = require("firebase/firestore");
const { execute } = require("firebase/firestore/pipelines");
const database = getFirestore(app, "enterprise");
const pipeline = database.pipeline();
Swift
let firestore = Firestore.firestore(database: "enterprise")
let pipeline = firestore.pipeline()

Kotlin

val firestore = Firebase.firestore("enterprise")
val pipeline = firestore.pipeline()

Java

FirebaseFirestore firestore = FirebaseFirestore.getInstance("enterprise");
PipelineSource pipeline = firestore.pipeline();
Python
firestore_client = firestore.client(default_app, "your-new-enterprise-database")
pipeline = firestore_client.pipeline()
जाएं
client, err := firestore.NewClientWithDatabase(ctx, projectID, databaseID)
if err != nil {
	fmt.Fprintf(w, "firestore.NewClientWithDatabase failed: %v", err)
	return err
}
defer client.Close()
pipeline := client.Pipeline().Collection("books")

बनावट

पाइपलाइन ऑपरेशन बनाते समय, कुछ शब्दों को समझना ज़रूरी है: स्टेज, एक्सप्रेशन, फ़ंक्शन, और सबक्वेरी रैपर.

किसी क्वेरी में स्टेज और एक्सप्रेशन दिखाने वाला उदाहरण

स्टेज: पाइपलाइन में एक या उससे ज़्यादा स्टेज हो सकते हैं. लॉजिक के हिसाब से, ये क्वेरी को लागू करने के लिए उठाए गए चरणों (या चरणों) की सीरीज़ को दिखाते हैं.

एक्सप्रेशन: स्टेज अक्सर किसी एक्सप्रेशन को स्वीकार करते हैं. इससे आपको ज़्यादा जटिल क्वेरी को ज़ाहिर करने की सुविधा मिलती है. एक्सप्रेशन आसान हो सकता है और इसमें eq("a", 1) जैसा कोई एक फ़ंक्शन शामिल हो सकता है. and(eq("a", 1), eq("b", 2)). जैसे एक्सप्रेशन को नेस्ट करके, ज़्यादा जटिल एक्सप्रेशन भी बनाए जा सकते हैं

सबक्वेरी रैपर: array() और scalar() जैसे फ़ंक्शन की मदद से, किसी स्टेज में नेस्ट की गई पाइपलाइन को एक्सप्रेशन के तौर पर एम्बेड किया जा सकता है.

फ़ील्ड / कॉन्सटैंट / वैरिएबल

पाइपलाइन ऑपरेशन, मुश्किल एक्सप्रेशन के साथ काम करते हैं. इसलिए, यह जानना ज़रूरी है कि कोई वैल्यू, फ़ील्ड, कॉन्स्टेंट या वैरिएबल में से किसे दिखाती है.

फ़ील्ड, दस्तावेज़ों में मौजूद डेटा को रेफ़र करते हैं और कॉन्सटैंट, किसी एक्सप्रेशन के आर्ग्युमेंट के तौर पर कोई भी वैल्यू तय करने की अनुमति देते हैं. वहीं, वैरिएबल, ऐसी अस्थायी वैल्यू तय करने और इस्तेमाल करने की अनुमति देते हैं जो प्रोसेस किए जा रहे दस्तावेज़ों के बजाय, क्वेरी के लागू होने के दायरे में आती हैं. यहां इन कॉन्सेप्ट के बारे में खास जानकारी दी गई है. क्वेरी के लागू होने के दौरान, वैरिएबल को पढ़ने और लिखने के तरीके के बारे में ज़्यादा जानने के लिए, let(...) स्टेज देखें.

फ़ील्ड कॉन्स्टेंट वैरिएबल
मकसद दस्तावेज़ों में फ़ील्ड ऐक्सेस करना या उन्हें सेव करना कोई तय वैल्यू डालें पाइपलाइन के एक्ज़ीक्यूशन के दौरान अस्थायी वैल्यू का इस्तेमाल करना
एसडीके का इस्तेमाल field("name") constant("val") variable("name")
स्कोप मौजूदा दस्तावेज़ के लिए लोकल सभी देशों में ग्लोबल से लेकर पाइपलाइन और सब-पाइपलाइन तक
Undefined Reference absent के बराबर है लागू नहीं रनटाइम से जुड़ी गड़बड़ी जनरेट करता है

प्रॉम्प्ट के उदाहरण:

Web

const pipeline = db.pipeline()
  .collection("cities")
  .where(field("name").equal(constant("Toronto")));
Swift
let pipeline = db.pipeline()
  .collection("cities")
  .where(Field("name").equal(Constant("Toronto")))

Kotlin

val pipeline = db.pipeline()
    .collection("cities")
    .where(field("name").equal(constant("Toronto")))

Java

Pipeline pipeline = db.pipeline()
    .collection("cities")
    .where(field("name").equal(constant("Toronto")));
Python
from google.cloud.firestore_v1.pipeline_expressions import Field, Constant

pipeline = (
    client.pipeline()
    .collection("cities")
    .where(Field.of("name").equal(Constant.of("Toronto")))
)
जाएं
pipeline := client.Pipeline().Collection("cities").
	Where(firestore.FieldOf("name").Equal(firestore.ConstantOf("Toronto")))

स्टेज बनाने की सेवा

इनपुट स्टेज

इनपुट स्टेज, क्वेरी का पहला स्टेज होता है. इससे उन दस्तावेज़ों का शुरुआती सेट तय होता है जिन पर क्वेरी की जा रही है. पाइपलाइन ऑपरेशन के लिए, यह काफ़ी हद तक मौजूदा क्वेरी से मिलता-जुलता है. इसमें ज़्यादातर क्वेरी, collection(...) या collection_group(...) स्टेज से शुरू होती हैं. इनपुट के दो नए स्टेज database() और documents(...) हैं. इनमें database(), डेटाबेस में मौजूद सभी दस्तावेज़ों को वापस लाने की अनुमति देता है. वहीं, documents(...), बैच रीड की तरह काम करता है.

Web

let results;

// Return all restaurants in San Francisco
results = await execute(db.pipeline().collection("cities/sf/restaurants"));

// Return all restaurants
results = await execute(db.pipeline().collectionGroup("restaurants"));

// Return all documents across all collections in the database (the entire database)
results = await execute(db.pipeline().database());

// Batch read of 3 documents
results = await execute(db.pipeline().documents([
  doc(db, "cities", "SF"),
  doc(db, "cities", "DC"),
  doc(db, "cities", "NY")
]));
Swift
var results: Pipeline.Snapshot

// Return all restaurants in San Francisco
results = try await db.pipeline().collection("cities/sf/restaurants").execute()

// Return all restaurants
results = try await db.pipeline().collectionGroup("restaurants").execute()

// Return all documents across all collections in the database (the entire database)
results = try await db.pipeline().database().execute()

// Batch read of 3 documents
results = try await db.pipeline().documents([
  db.collection("cities").document("SF"),
  db.collection("cities").document("DC"),
  db.collection("cities").document("NY")
]).execute()

Kotlin

var results: Task<Pipeline.Snapshot>

// Return all restaurants in San Francisco
results = db.pipeline().collection("cities/sf/restaurants").execute()

// Return all restaurants
results = db.pipeline().collectionGroup("restaurants").execute()

// Return all documents across all collections in the database (the entire database)
results = db.pipeline().database().execute()

// Batch read of 3 documents
results = db.pipeline().documents(
    db.collection("cities").document("SF"),
    db.collection("cities").document("DC"),
    db.collection("cities").document("NY")
).execute()

Java

Task<Pipeline.Snapshot> results;

// Return all restaurants in San Francisco
results = db.pipeline().collection("cities/sf/restaurants").execute();

// Return all restaurants
results = db.pipeline().collectionGroup("restaurants").execute();

// Return all documents across all collections in the database (the entire database)
results = db.pipeline().database().execute();

// Batch read of 3 documents
results = db.pipeline().documents(
    db.collection("cities").document("SF"),
    db.collection("cities").document("DC"),
    db.collection("cities").document("NY")
).execute();
Python
# Return all restaurants in San Francisco
results = client.pipeline().collection("cities/sf/restaurants").execute()

# Return all restaurants
results = client.pipeline().collection_group("restaurants").execute()

# Return all documents across all collections in the database (the entire database)
results = client.pipeline().database().execute()

# Batch read of 3 documents
results = (
    client.pipeline()
    .documents(
        client.collection("cities").document("SF"),
        client.collection("cities").document("DC"),
        client.collection("cities").document("NY"),
    )
    .execute()
)
जाएं
// Return all restaurants in San Francisco
results1, err := client.Pipeline().Collection("cities/sf/restaurants").Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

// Return all restaurants
results2, err := client.Pipeline().CollectionGroup("restaurants").Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

// Return all documents across all collections in the database (the entire database)
results3, err := client.Pipeline().Database().Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

// Batch read of 3 documents
results4, err := client.Pipeline().
	Documents([]*firestore.DocumentRef{
		client.Collection("cities").Doc("SF"),
		client.Collection("cities").Doc("DC"),
		client.Collection("cities").Doc("NY"),
	}).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

अन्य सभी स्टेज की तरह, इनपुट के इन स्टेज से मिलने वाले नतीजों का क्रम तय नहीं होता. अगर किसी खास क्रम की ज़रूरत है, तो हमेशा sort(...) ऑपरेटर जोड़ना चाहिए.

कहां

where(...) स्टेज, पिछली स्टेज से जनरेट हुए दस्तावेज़ों पर स्टैंडर्ड फ़िल्टर ऑपरेशन के तौर पर काम करता है. साथ ही, यह ज़्यादातर मौजूदा क्वेरी के लिए, मौजूदा "where" सिंटैक्स को दिखाता है. ऐसा कोई भी दस्तावेज़ जिसमें दिए गए एक्सप्रेशन की वैल्यू true नहीं होती है उसे दिखाए गए दस्तावेज़ों से फ़िल्टर कर दिया जाता है.

एक से ज़्यादा where(...) स्टेटमेंट को एक साथ जोड़ा जा सकता है. साथ ही, ये and(...) एक्सप्रेशन के तौर पर काम करते हैं. उदाहरण के लिए, यहां दी गई दोनों क्वेरी का लॉजिक एक जैसा है और इन्हें एक-दूसरे की जगह इस्तेमाल किया जा सकता है.

Web

let results;

results = await execute(db.pipeline().collection("books")
  .where(field("rating").equal(5))
  .where(field("published").lessThan(1900))
);

results = await execute(db.pipeline().collection("books")
  .where(and(field("rating").equal(5), field("published").lessThan(1900)))
);
Swift
var results: Pipeline.Snapshot

results = try await db.pipeline().collection("books")
  .where(Field("rating").equal(5))
  .where(Field("published").lessThan(1900))
  .execute()

results = try await db.pipeline().collection("books")
  .where(Field("rating").equal(5) && Field("published").lessThan(1900))
  .execute()

Kotlin

var results: Task<Pipeline.Snapshot>

results = db.pipeline().collection("books")
    .where(field("rating").equal(5))
    .where(field("published").lessThan(1900))
    .execute()

results = db.pipeline().collection("books")
    .where(Expression.and(field("rating").equal(5),
      field("published").lessThan(1900)))
    .execute()

Java

Task<Pipeline.Snapshot> results;

results = db.pipeline().collection("books")
    .where(field("rating").equal(5))
    .where(field("published").lessThan(1900))
    .execute();

results = db.pipeline().collection("books")
    .where(Expression.and(
        field("rating").equal(5),
        field("published").lessThan(1900)
    ))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import And, Field

results = (
    client.pipeline()
    .collection("books")
    .where(Field.of("rating").equal(5))
    .where(Field.of("published").less_than(1900))
    .execute()
)

results = (
    client.pipeline()
    .collection("books")
    .where(And(Field.of("rating").equal(5), Field.of("published").less_than(1900)))
    .execute()
)
जाएं
results1, err := client.Pipeline().
	Collection("books").
	Where(firestore.FieldOf("rating").Equal(5)).
	Where(firestore.FieldOf("published").LessThan(1900)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

results2, err := client.Pipeline().
	Collection("books").
	Where(firestore.And(
		firestore.FieldOf("rating").Equal(5),
		firestore.FieldOf("published").LessThan(1900),
	)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

फ़ील्ड चुनना / जोड़ना और हटाना

select(...), add_fields(...), और remove_fields(...), इन सभी की मदद से, पिछले चरण से मिले फ़ील्ड में बदलाव किया जा सकता है. इन तीनों को आम तौर पर, प्रोजेक्शन-स्टाइल स्टेज कहा जाता है.

select(...) और add_fields(...) की मदद से, उपयोगकर्ता के दिए गए फ़ील्ड के नाम के लिए, एक्सप्रेशन के नतीजे की जानकारी दी जा सकती है. select(...) सिर्फ़ उन दस्तावेज़ों को दिखाएगा जिनमें फ़ील्ड के नाम तय किए गए हैं. वहीं, add_fields(...) पिछले चरण के स्कीमा को बड़ा करता है. ऐसा हो सकता है कि यह एक जैसे फ़ील्ड के नाम वाली वैल्यू को ओवरराइट कर दे.

remove_fields(...) का इस्तेमाल करके, फ़ील्ड के उस सेट के बारे में बताया जा सकता है जिसे पिछले चरण से हटाना है. ऐसे फ़ील्ड के नाम डालने से कोई कार्रवाई नहीं होती जो मौजूद नहीं हैं.

नीचे दिया गया नतीजों में दिखने वाले फ़ील्ड सीमित करना सेक्शन देखें. आम तौर पर, इस तरह के स्टेज का इस्तेमाल करके, नतीजों को सिर्फ़ उन फ़ील्ड तक सीमित किया जाता है जिनकी क्लाइंट को ज़रूरत होती है. इससे ज़्यादातर क्वेरी के लिए, लागत और इंतज़ार का समय कम करने में मदद मिलती है.

एग्रीगेट / अलग-अलग

aggregate(...) स्टेज की मदद से, इनपुट दस्तावेज़ों पर एग्रीगेशन की सीरीज़ को लागू किया जा सकता है. डिफ़ॉल्ट रूप से, सभी दस्तावेज़ों को एक साथ एग्रीगेट किया जाता है. हालांकि, वैकल्पिक grouping आर्ग्युमेंट दिया जा सकता है. इससे इनपुट दस्तावेज़ों को अलग-अलग बकेट में एग्रीगेट किया जा सकता है.

Web

const results = await execute(db.pipeline()
  .collection("books")
  .aggregate(
    field("rating").average().as("avg_rating")
  )
  .distinct(field("genre"))
);
Swift
let results = try await db.pipeline()
  .collection("books")
  .aggregate([
    Field("rating").average().as("avg_rating")
  ], groups: [
    Field("genre")
  ])
  .execute()

Kotlin

val results = db.pipeline()
    .collection("books")
    .aggregate(
        AggregateStage
            .withAccumulators(AggregateFunction.average("rating").alias("avg_rating"))
            .withGroups(field("genre"))
    )
    .execute()

Java

Task<Pipeline.Snapshot> results = db.pipeline()
    .collection("books")
    .aggregate(AggregateStage
        .withAccumulators(
            AggregateFunction.average("rating").alias("avg_rating"))
        .withGroups(field("genre")))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

results = (
    client.pipeline()
    .collection("books")
    .aggregate(
        Field.of("rating").average().as_("avg_rating"), groups=[Field.of("genre")]
    )
    .execute()
)
जाएं
snapshot := client.Pipeline().
	Collection("books").
	Aggregate(
		firestore.Accumulators(firestore.Average("rating").As("avg_rating")),
		firestore.WithAggregateGroups("genre"),
	).
	Execute(ctx)

groupings की वैल्यू न देने पर, यह स्टेज सिर्फ़ एक दस्तावेज़ जनरेट करेगा. अगर वैल्यू दी जाती है, तो groupings की वैल्यू के हर यूनीक कॉम्बिनेशन के लिए एक दस्तावेज़ जनरेट होगा.

distinct(...) स्टेज, एक आसान एग्रीगेशन ऑपरेटर है. इसकी मदद से, बिना किसी एक्युमलेटर के सिर्फ़ यूनीक groupings जनरेट किए जा सकते हैं. अन्य सभी मामलों में, यह aggregate(...) की तरह ही काम करता है. यहां दिए गए उदाहरण में यह जानकारी दिखती है:

Web

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

Kotlin

val results = db.pipeline()
    .collection("books")
    .distinct(
        field("author").toUpper().alias("author"),
        field("genre")
    )
    .execute()

Java

Task<Pipeline.Snapshot> results = db.pipeline()
    .collection("books")
    .distinct(
        field("author").toUpper().alias("author"),
        field("genre")
    )
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

results = (
    client.pipeline()
    .collection("books")
    .distinct(Field.of("author").to_upper().as_("author"), "genre")
    .execute()
)
जाएं
snapshot := client.Pipeline().
	Collection("books").
	Distinct(firestore.Fields(
		firestore.ToUpper(firestore.FieldOf("author")).As("author"),
		firestore.FieldOf("genre"),
	)).
	Execute(ctx)

फ़ंक्शन

फ़ंक्शन, एक्सप्रेशन और जटिल क्वेरी बनाने के लिए एक बिल्डिंग ब्लॉक होते हैं. उदाहरणों के साथ फ़ंक्शन की पूरी सूची देखने के लिए, फ़ंक्शन रेफ़रंस देखें. एक सामान्य क्वेरी के स्ट्रक्चर को ध्यान में रखें:

किसी क्वेरी में स्टेज और फ़ंक्शन दिखाने वाला उदाहरण

कई स्टेज में ऐसे एक्सप्रेशन इस्तेमाल किए जा सकते हैं जिनमें एक या उससे ज़्यादा फ़ंक्शन शामिल हों. फ़ंक्शन का सबसे ज़्यादा इस्तेमाल, where(...) और select(...) स्टेज में किया जाएगा. आपको दो मुख्य तरह के फ़ंक्शन के बारे में जानकारी होनी चाहिए:

Web

let results;

// Type 1: Scalar (for use in non-aggregation stages)
// Example: Return the min store price for each book.
results = await execute(db.pipeline().collection("books")
  .select(field("current").logicalMinimum(field("updated")).as("price_min"))
);

// Type 2: Aggregation (for use in aggregate stages)
// Example: Return the min price of all books.
results = await execute(db.pipeline().collection("books")
  .aggregate(field("price").minimum().as("min_price"))
);
Swift
var results: Pipeline.Snapshot

// Type 1: Scalar (for use in non-aggregation stages)
// Example: Return the min store price for each book.
results = try await db.pipeline().collection("books")
  .select([
    Field("current").logicalMinimum(["updated"]).as("price_min")
  ])
  .execute()

// Type 2: Aggregation (for use in aggregate stages)
// Example: Return the min price of all books.
results = try await db.pipeline().collection("books")
  .aggregate([Field("price").minimum().as("min_price")])
  .execute()

Kotlin

var results: Task<Pipeline.Snapshot>

// Type 1: Scalar (for use in non-aggregation stages)
// Example: Return the min store price for each book.
results = db.pipeline().collection("books")
    .select(
        field("current").logicalMinimum("updated").alias("price_min")
    )
    .execute()

// Type 2: Aggregation (for use in aggregate stages)
// Example: Return the min price of all books.
results = db.pipeline().collection("books")
    .aggregate(AggregateFunction.minimum("price").alias("min_price"))
    .execute()

Java

Task<Pipeline.Snapshot> results;

// Type 1: Scalar (for use in non-aggregation stages)
// Example: Return the min store price for each book.
results = db.pipeline().collection("books")
    .select(
        field("current").logicalMinimum("updated").alias("price_min")
    )
    .execute();

// Type 2: Aggregation (for use in aggregate stages)
// Example: Return the min price of all books.
results = db.pipeline().collection("books")
    .aggregate(AggregateFunction.minimum("price").alias("min_price"))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

# Type 1: Scalar (for use in non-aggregation stages)
# Example: Return the min store price for each book.
results = (
    client.pipeline()
    .collection("books")
    .select(
        Field.of("current").logical_minimum(Field.of("updated")).as_("price_min")
    )
    .execute()
)

# Type 2: Aggregation (for use in aggregate stages)
# Example: Return the min price of all books.
results = (
    client.pipeline()
    .collection("books")
    .aggregate(Field.of("price").minimum().as_("min_price"))
    .execute()
)
जाएं
// Type 1: Scalar (for use in non-aggregation stages)
// Example: Return the min store price for each book.
results1, err := client.Pipeline().
	Collection("books").
	Select(firestore.Fields(
		firestore.LogicalMinimum(firestore.FieldOf("current"), firestore.FieldOf("updated")).As("price_min"),
	)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

// Type 2: Aggregation (for use in aggregate stages)
// Example: Return the min price of all books.
results2, err := client.Pipeline().
	Collection("books").
	Aggregate(firestore.Accumulators(
		firestore.Minimum("price").As("min_price"),
	)).
	Execute(ctx).Results().GetAll()
if err != nil {
	fmt.Fprintf(w, "GetAll failed: %v", err)
	return err
}

सीमाएं

Enterprise वर्शन में, क्वेरी के फ़ॉर्मैट पर कोई पाबंदी नहीं होती. दूसरे शब्दों में, IN या OR क्वेरी में, आपके पास वैल्यू की कोई तय सीमा नहीं होती. इसके बजाय, आपको दो मुख्य सीमाओं के बारे में पता होना चाहिए:

  • समयसीमा: 60 सेकंड (स्टैंडर्ड वर्शन की तरह).
  • मेमोरी का इस्तेमाल: क्वेरी के दौरान, मटीरियलाइज़्ड डेटा की सीमा 128 MiB है.

गड़बड़ियां

कई वजहों से, क्वेरी का जवाब न मिलने की समस्या आ सकती है. यहां आम तौर पर होने वाली गड़बड़ियों और उनसे जुड़ी कार्रवाई का लिंक दिया गया है:

गड़बड़ी का कोड कार्रवाई
DEADLINE_EXCEEDED जिस क्वेरी को चलाया जा रहा है उसे पूरा होने में 60 सेकंड से ज़्यादा समय लग रहा है. इसलिए, उसे और ऑप्टिमाइज़ करने की ज़रूरत है. सलाह के लिए, परफ़ॉर्मेंस सेक्शन देखें. अगर आपको समस्या की असल वजह पता नहीं चल पा रही है, तो टीम से संपर्क करें.
RESOURCE_EXHAUSTED जिस क्वेरी को चलाया जा रहा है वह मेमोरी की सीमाओं से ज़्यादा है. इसलिए, उसे और ऑप्टिमाइज़ करने की ज़रूरत है. सलाह के लिए, परफ़ॉर्मेंस सेक्शन देखें. अगर आपको समस्या की असल वजह पता नहीं चल पा रही है, तो टीम से संपर्क करें.
INTERNAL मदद पाने के लिए, टीम से संपर्क करें.

परफ़ॉर्मेंस

Enterprise वर्शन के डेटाबेस के लिए, यह ज़रूरी नहीं है कि इंडेक्स हमेशा मौजूद हो. इसका मतलब है कि किसी क्वेरी को पूरा होने में, मौजूदा क्वेरी की तुलना में ज़्यादा समय लग सकता है. मौजूदा क्वेरी, FAILED_PRECONDITION इंडेक्स मौजूद नहीं है वाली गड़बड़ी की वजह से तुरंत फ़ेल हो जाती हैं. पाइपलाइन ऑपरेशन की परफ़ॉर्मेंस को बेहतर बनाने के लिए, कुछ कदम उठाए जा सकते हैं.

इंडेक्स बनाना

इस्तेमाल किया गया इंडेक्स

क्वेरी की जानकारी देने वाली सुविधा से, यह पता लगाया जा सकता है कि आपकी क्वेरी को इंडेक्स से पूरा किया जा रहा है या टेबल स्कैन जैसे कम असरदार ऑपरेशन का इस्तेमाल किया जा रहा है. अगर आपकी क्वेरी का जवाब इंडेक्स से पूरी तरह से नहीं मिल रहा है, तो निर्देशों का पालन करके इंडेक्स बनाया जा सकता है.

इंडेक्स बनाना

इंडेक्स बनाने के लिए, इंडेक्स मैनेजमेंट से जुड़े मौजूदा दस्तावेज़ में दिए गए निर्देशों का पालन किया जा सकता है. इंडेक्स बनाने से पहले, Cloud Firestore में इंडेक्स के लिए सबसे सही तरीके जानें. यह पक्का करने के लिए कि आपकी क्वेरी, इंडेक्स का फ़ायदा ले सके, यहां दिए गए क्रम में फ़ील्ड के साथ इंडेक्स बनाने के लिए, सबसे सही तरीके अपनाएं:

  1. वे सभी फ़ील्ड जो इक्वालिटी फ़िल्टर में इस्तेमाल किए जाएंगे (किसी भी क्रम में)
  2. वे सभी फ़ील्ड जिनके हिसाब से डेटा को क्रम से लगाया जाएगा (उसी क्रम में)
  3. क्वेरी की शर्त के हिसाब से, चुने जाने की संभावना के घटते क्रम में, रेंज या असमानता वाले फ़िल्टर में इस्तेमाल किए जाने वाले फ़ील्ड

उदाहरण के लिए, इस क्वेरी के लिए,

Web

const results = await execute(db.pipeline()
  .collection("books")
  .where(field("published").lessThan(1900))
  .where(field("genre").equal("Science Fiction"))
  .where(field("rating").greaterThan(4.3))
  .sort(field("published").descending())
);
Swift
let results = try await db.pipeline()
  .collection("books")
  .where(Field("published").lessThan(1900))
  .where(Field("genre").equal("Science Fiction"))
  .where(Field("rating").greaterThan(4.3))
  .sort([Field("published").descending()])
  .execute()

Kotlin

val results = db.pipeline()
    .collection("books")
    .where(field("published").lessThan(1900))
    .where(field("genre").equal("Science Fiction"))
    .where(field("rating").greaterThan(4.3))
    .sort(field("published").descending())
    .execute()

Java

Task<Pipeline.Snapshot> results = db.pipeline()
    .collection("books")
    .where(field("published").lessThan(1900))
    .where(field("genre").equal("Science Fiction"))
    .where(field("rating").greaterThan(4.3))
    .sort(field("published").descending())
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

results = (
    client.pipeline()
    .collection("books")
    .where(Field.of("published").less_than(1900))
    .where(Field.of("genre").equal("Science Fiction"))
    .where(Field.of("rating").greater_than(4.3))
    .sort(Field.of("published").descending())
    .execute()
)
जाएं
snapshot := client.Pipeline().
	Collection("books").
	Where(firestore.FieldOf("published").LessThan(1900)).
	Where(firestore.FieldOf("genre").Equal("Science Fiction")).
	Where(firestore.FieldOf("rating").GreaterThan(4.3)).
	Sort(firestore.Orders(firestore.Descending(firestore.FieldOf("published")))).
	Execute(ctx)

सुझाया गया इंडेक्स, (genre [...], published DESC, avg_rating DESC). के लिए books पर कलेक्शन स्कोप इंडेक्स है

इंडेक्स डेंसिटी

Cloud Firestore, स्पार्स और नॉन-स्पार्स इंडेक्स के साथ काम करता है. ज़्यादा जानकारी के लिए, इंडेक्स डेंसिटी देखें.

कवर्ड क्वेरी + सेकंडरी इंडेक्स

अगर दिखाए जा रहे सभी फ़ील्ड किसी सेकंडरी इंडेक्स में मौजूद हैं, तो Cloud Firestore पूरा दस्तावेज़ फ़ेच करने की प्रोसेस को स्किप कर सकता है. साथ ही, इंडेक्स से नतीजे दिखा सकता है. आम तौर पर, इससे इंतज़ार का समय (और लागत) काफ़ी कम हो जाता है. नीचे दी गई सैंपल क्वेरी का इस्तेमाल करके:

Web

const results = await execute(db.pipeline()
  .collection("books")
  .where(field("category").like("%fantasy%"))
  .where(field("title").exists())
  .where(field("author").exists())
  .select(field("title"), field("author"))
);
Swift
let results = try await db.pipeline()
  .collection("books")
  .where(Field("category").like("%fantasy%"))
  .where(Field("title").exists())
  .where(Field("author").exists())
  .select([Field("title"), Field("author")])
  .execute()

Kotlin

val results = db.pipeline()
    .collection("books")
    .where(field("category").like("%fantasy%"))
    .where(field("title").exists())
    .where(field("author").exists())
    .select(field("title"), field("author"))
    .execute()

Java

Task<Pipeline.Snapshot> results = db.pipeline()
    .collection("books")
    .where(field("category").like("%fantasy%"))
    .where(field("title").exists())
    .where(field("author").exists())
    .select(field("title"), field("author"))
    .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field

results = (
    client.pipeline()
    .collection("books")
    .where(Field.of("category").like("%fantasy%"))
    .where(Field.of("title").exists())
    .where(Field.of("author").exists())
    .select("title", "author")
    .execute()
)
जाएं
snapshot := client.Pipeline().
	Collection("books").
	Where(firestore.FieldOf("category").Like("%fantasy%")).
	Where(firestore.FieldOf("title").FieldExists()).
	Where(firestore.FieldOf("author").FieldExists()).
	Select(firestore.Fields("title", "author")).
	Execute(ctx)

अगर डेटाबेस में पहले से ही (category [...], title [...], author [...]) के लिए books पर कलेक्शन स्कोप इंडेक्स मौजूद है, तो यह मुख्य दस्तावेज़ों से कुछ भी फ़ेच करने से बच सकता है. इस मामले में, इंडेक्स में मौजूद क्रम से कोई फ़र्क़ नहीं पड़ता. इसे दिखाने के लिए, [...] का इस्तेमाल किया जाता है.

नतीजों में दिखने वाले फ़ील्ड को सीमित करना

डिफ़ॉल्ट रूप से, Cloud Firestore क्वेरी किसी दस्तावेज़ के सभी फ़ील्ड दिखाती है. यह रिलेशनल सिस्टम में SELECT * की तरह काम करती है. हालांकि, अगर आपके ऐप्लिकेशन को फ़ील्ड के सिर्फ़ एक सबसेट की ज़रूरत है, तो इस फ़िल्टर को सर्वर-साइड पर पुश करने के लिए, select(...) या restrict(...) स्टेज का इस्तेमाल किया जा सकता है. इससे, रिस्पॉन्स का साइज़ कम हो जाएगा. साथ ही, नेटवर्क इग्रेस डेटा ट्रैफ़िक की लागत कम हो जाएगी और इंतज़ार का समय कम हो जाएगा.

समस्या निवारण टूल

क्वेरी के बारे में जानकारी

Query Explain की मदद से, एक्ज़ीक्यूशन मेट्रिक और इस्तेमाल किए गए इंडेक्स के बारे में जानकारी देखी जा सकती है.

मेट्रिक

अगर पाइपलाइन ऑपरेशन, मौजूदा Cloud Firestore मेट्रिक के साथ पूरी तरह से इंटिग्रेट हैं.

आम तौर पर होने वाली समस्याएं / सीमाएं

खास इंडेक्स

पाइपलाइन ऑपरेशन, फ़िलहाल मौजूदा array-contains और vector इंडेक्स टाइप के साथ काम नहीं करते. ऐसी क्वेरी को अस्वीकार करने के बजाय, Cloud Firestore अन्य मौजूदा ascending और descending इंडेक्स का इस्तेमाल करने की कोशिश करेगा. इस वजह से, ऐसा हो सकता है कि array_contains या find_nearest एक्सप्रेशन, मौजूदा एक्सप्रेशन की तुलना में धीमे हों.

रीयल-टाइम और ऑफ़लाइन सहायता

पाइपलाइन ऑपरेशन में रीयलटाइम और ऑफ़लाइन सुविधाएं नहीं होती हैं.

आगे क्या करना है