database - tak - देवनागरी




क्लाउड फायरस्टार के साथ एक संग्रह में दस्तावेजों की संख्या की संख्या कैसे प्राप्त करें (4)

फायरस्टार में, मैं एक संग्रह में दस्तावेजों की कुल संख्या कैसे प्राप्त कर सकता हूं?

उदाहरण के लिए यदि मेरे पास है

/people
    /123456
        /name - 'John'
    /456789
        /name - 'Jane'

मैं पूछना चाहता हूं कि मेरे पास कितने लोग हैं और 2 हैं।

मैं / लोगों पर एक क्वेरी कर सकता था और फिर लौटाए गए परिणामों की लंबाई प्राप्त कर सकता था, लेकिन यह एक बेकार लगता है, खासकर क्योंकि मैं बड़े डेटासेट पर ऐसा कर रहा हूं।


एकत्रीकरण जाने का तरीका है (फ़ायरबेस फ़ंक्शंस इन एकत्रीकरण को अपडेट करने के लिए अनुशंसित तरीके की तरह दिखते हैं क्योंकि ग्राहक पक्ष उस उपयोगकर्ता को जानकारी उजागर करता है जिसे आप उजागर नहीं करना चाहते हैं) https://firebase.google.com/docs/firestore/solutions/aggregation

एक और तरीका (अनुशंसित नहीं) जो बड़ी सूचियों के लिए अच्छा नहीं है और इसमें पूरी सूची डाउनलोड करना शामिल है: res.size इस उदाहरण की तरह:

this.afs.collection(myCollection).valueChanges().subscribe( values => console.log(values.length));

क्लाउड फ़ंक्शन के साथ बड़े संग्रह के लिए दस्तावेजों की संख्या की सावधानीपूर्वक गणना करें। यह फायरस्टार डेटाबेस के साथ थोड़ा जटिल है यदि आप हर संग्रह के लिए एक पूर्व-निर्धारित काउंटर चाहते हैं।

इस तरह कोड इस मामले में काम नहीं करता है:

export const customerCounterListener = 
    functions.firestore.document('customers/{customerId}')
    .onWrite((change, context) => {

    // on create
    if (!change.before.exists && change.after.exists) {
        return firestore
                 .collection('metadatas')
                 .doc('customers')
                 .get()
                 .then(docSnap =>
                     docSnap.ref.set({
                         count: docSnap.data().count + 1
                     }))
    // on delete
    } else if (change.before.exists && !change.after.exists) {
        return firestore
                 .collection('metadatas')
                 .doc('customers')
                 .get()
                 .then(docSnap =>
                     docSnap.ref.set({
                         count: docSnap.data().count - 1
                     }))
    }

    return null;
});

इसका कारण यह है कि हर क्लाउड फायरस्टार ट्रिगर को बेरोजगार होना पड़ता है, क्योंकि फायरस्टार प्रलेखन कहता है: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees

उपाय

तो, अपने कोड के कई निष्पादन को रोकने के लिए, आपको घटनाओं और लेनदेन के साथ प्रबंधन करने की आवश्यकता है। बड़े संग्रह काउंटरों को संभालने का यह मेरा विशेष तरीका है:

const executeOnce = (change, context, task) => {
    const eventRef = firestore.collection('events').doc(context.eventId);

    return firestore.runTransaction(t =>
        t
         .get(eventRef)
         .then(docSnap => (docSnap.exists ? null : task(t)))
         .then(() => t.set(eventRef, { processed: true }))
    );
};

const documentCounter = collectionName => (change, context) =>
    executeOnce(change, context, t => {
        // on create
        if (!change.before.exists && change.after.exists) {
            return t
                    .get(firestore.collection('metadatas')
                    .doc(collectionName))
                    .then(docSnap =>
                        t.set(docSnap.ref, {
                            count: ((docSnap.data() && docSnap.data().count) || 0) + 1
                        }));
        // on delete
        } else if (change.before.exists && !change.after.exists) {
            return t
                     .get(firestore.collection('metadatas')
                     .doc(collectionName))
                     .then(docSnap =>
                        t.set(docSnap.ref, {
                            count: docSnap.data().count - 1
                        }));
        }

        return null;
    });

यहां मामलों का उपयोग करें:

/**
 * Count documents in articles collection.
 */
exports.articlesCounter = functions.firestore
    .document('articles/{id}')
    .onWrite(documentCounter('articles'));

/**
 * Count documents in customers collection.
 */
exports.customersCounter = functions.firestore
    .document('customers/{id}')
    .onWrite(documentCounter('customers'));

जैसा कि आप देख सकते हैं, एकाधिक निष्पादन को रोकने के लिए कुंजी संदर्भ ऑब्जेक्ट में EventId नामक संपत्ति है। यदि फ़ंक्शन को एक ही इवेंट के लिए कई बार हैंडल किया गया है, तो ईवेंट आईडी सभी मामलों में समान होगी। दुर्भाग्य से, आपके डेटाबेस में "ईवेंट" संग्रह होना चाहिए।


वर्तमान में आपके पास 3 विकल्प हैं:

विकल्प 1: ग्राहक पक्ष

यह मूल रूप से आपके द्वारा उल्लिखित दृष्टिकोण है। संग्रह से सभी का चयन करें और ग्राहक पक्ष पर भरोसा करें। यह छोटे डेटासेट के लिए पर्याप्त रूप से काम करता है, लेकिन जाहिर है कि अगर डेटासेट बड़ा नहीं होता है।

विकल्प 2: राइट-टाइम सर्वश्रेष्ठ प्रयास

इस दृष्टिकोण के साथ, आप संग्रह से प्रत्येक जोड़ और विलोपन के लिए एक काउंटर अपडेट करने के लिए क्लाउड फ़ंक्शंस का उपयोग कर सकते हैं।

यह किसी भी डेटासेट आकार के लिए अच्छी तरह से काम करता है, जब तक कि परिवर्धन / विलोपन केवल 1 प्रति सेकंड से कम या उसके बराबर दर पर होते हैं। यह आपको लगभग वर्तमान गणना तुरंत देने के लिए पढ़ने के लिए एक एकल दस्तावेज़ देता है।

यदि आपको प्रति सेकंड 1 से अधिक की आवश्यकता है, तो आपको हमारे प्रलेखन के अनुसार वितरित काउंटरों को लागू करने की आवश्यकता है।

विकल्प 3: राइट-टाइम सटीक

क्लाउड फ़ंक्शंस का उपयोग करने के बजाय, अपने क्लाइंट में आप दस्तावेज़ को जोड़ते या हटाते समय उसी समय काउंटर को अपडेट कर सकते हैं। इसका मतलब यह है कि काउंटर भी चालू होगा, लेकिन आपको इस तर्क को शामिल करने के लिए सुनिश्चित करना होगा कि आप कहीं भी दस्तावेज़ जोड़ें या हटाएं।

विकल्प 2 की तरह, आपको वितरित काउंटरों को लागू करने की आवश्यकता होगी यदि आप प्रति सेकंड से अधिक करना चाहते हैं


दान उत्तर के बाद : आप अपने डेटाबेस में एक अलग काउंटर रख सकते हैं और इसे बनाए रखने के लिए क्लाउड फ़ंक्शंस का उपयोग कर सकते हैं। ( समय-सर्वोत्तम प्रयास )

// Example of performing an increment when item is added
module.exports.incrementIncomesCounter = collectionRef.onCreate(event => {
  const counterRef = event.data.ref.firestore.doc('counters/incomes')

  counterRef.get()
  .then(documentSnapshot => {
    const currentCount = documentSnapshot.exists ? documentSnapshot.data().count : 0

    counterRef.set({
      count: Number(currentCount) + 1
    })
    .then(() => {
      console.log('counter has increased!')
    })
  })
})

यह कोड आपको यह करने का पूरा उदाहरण दिखाता है: https://gist.github.com/saintplay/3f965e0aea933a1129cc2c9a823e74d7





google-cloud-firestore