शेयर किए गए टाइमस्टैंप

अगर किसी कलेक्शन में, क्रम से इंडेक्स की गई वैल्यू वाले दस्तावेज़ शामिल हैं, तो Cloud Firestore लिखने की दर को हर सेकंड 500 बार लिखने तक सीमित कर देता है. इस पेज पर, इस सीमा से बचने के लिए, किसी दस्तावेज़ के फ़ील्ड को शार्ड करने का तरीका बताया गया है. सबसे पहले, "क्रम से इंडेक्स किए गए फ़ील्ड" की परिभाषा जानते हैं. साथ ही, यह भी जानते हैं कि यह सीमा कब लागू होती है.

क्रम से इंडेक्स किए गए फ़ील्ड

"क्रम से इंडेक्स किए गए फ़ील्ड" का मतलब है, दस्तावेज़ों का ऐसा कलेक्शन जिसमें क्रम से बढ़ने या घटने वाला इंडेक्स किया गया फ़ील्ड शामिल हो. ज़्यादातर मामलों में, इसका मतलब timestamp फ़ील्ड होता है. हालांकि, क्रम से बढ़ने या घटने वाली किसी भी फ़ील्ड वैल्यू से, हर सेकंड 500 बार लिखने की सीमा लागू हो सकती है.

उदाहरण के लिए, अगर ऐप्लिकेशन, userid वैल्यू इस तरह असाइन करता है, तो इंडेक्स किए गए फ़ील्ड userid वाले user दस्तावेज़ों के कलेक्शन पर यह सीमा लागू होती है:

  • 1281, 1282, 1283, 1284, 1285, ...

हालांकि, सभी timestamp फ़ील्ड पर यह सीमा लागू नहीं होती. अगर timestamp फ़ील्ड, रैंडम तरीके से डिस्ट्रिब्यूट की गई वैल्यू को ट्रैक करता है, तो लिखने की सीमा लागू नहीं होती. फ़ील्ड की असल वैल्यू से भी कोई फ़र्क़ नहीं पड़ता. सिर्फ़ यह मायने रखता है कि फ़ील्ड की वैल्यू क्रम से बढ़ रही है या घट रही है. उदाहरण के लिए, क्रम से बढ़ने वाली फ़ील्ड वैल्यू के इन दोनों सेट पर, लिखने की सीमा लागू होती है:

  • 100000, 100001, 100002, 100003, ...
  • 0, 1, 2, 3, ...

टाइमस्टैंप फ़ील्ड को शार्ड करना

मान लें कि आपका ऐप्लिकेशन, क्रम से बढ़ने वाले timestamp फ़ील्ड का इस्तेमाल करता है. अगर आपका ऐप्लिकेशन, किसी भी क्वेरी में timestamp फ़ील्ड का इस्तेमाल नहीं करता है, तो टाइमस्टैंप फ़ील्ड को इंडेक्स न करके, हर सेकंड 500 बार लिखने की सीमा को हटाया जा सकता है. अगर आपको अपनी क्वेरी के लिए timestamp फ़ील्ड की ज़रूरत है, तो शार्ड किए गए टाइमस्टैंप का इस्तेमाल करके, इस सीमा से बचा जा सकता है:

  1. timestamp फ़ील्ड के साथ, shard फ़ील्ड जोड़ें. shard फ़ील्ड के लिए, 1..n अलग-अलग वैल्यू का इस्तेमाल करें. इससे कलेक्शन के लिए, लिखने की सीमा बढ़कर 500*n हो जाती है. हालांकि, आपको n क्वेरी को एग्रीगेट करना होगा.
  2. हर दस्तावेज़ को रैंडम तरीके से shard वैल्यू असाइन करने के लिए, लिखने के लॉजिक को अपडेट करें.
  3. शार्ड किए गए नतीजों के सेट को एग्रीगेट करने के लिए, अपनी क्वेरी अपडेट करें.
  4. shard फ़ील्ड और timestamp फ़ील्ड, दोनों के लिए सिंगल-फ़ील्ड इंडेक्स बंद करें. timestamp फ़ील्ड वाले मौजूदा कंपोज़िट इंडेक्स मिटाएं.
  5. अपडेट की गई क्वेरी के लिए, नए कंपोज़िट इंडेक्स बनाएं. किसी इंडेक्स में फ़ील्ड का क्रम मायने रखता है. साथ ही, shard फ़ील्ड, timestamp फ़ील्ड से पहले होना चाहिए. timestamp फ़ील्ड वाले किसी भी इंडेक्स में, shard फ़ील्ड भी शामिल होना चाहिए.

शार्ड किए गए टाइमस्टैंप को सिर्फ़ उन इस्तेमाल के मामलों में लागू करें जहां हर सेकंड 500 से ज़्यादा बार लिखने की दर बनी रहती है. अन्य मामलों में, यह समय से पहले किया गया ऑप्टिमाइज़ेशन है. timestamp फ़ील्ड को शार्ड करने से, हर सेकंड 500 बार लिखने की पाबंदी हट जाती है. हालांकि, इसके लिए क्लाइंट-साइड क्वेरी एग्रीगेशन की ज़रूरत होती है.

यहां दिए गए उदाहरणों में, timestamp फ़ील्ड को शार्ड करने और शार्ड किए गए नतीजों के सेट की क्वेरी करने का तरीका बताया गया है.

डेटा मॉडल और क्वेरी का उदाहरण

उदाहरण के लिए, मान लें कि आपके पास ऐसा ऐप्लिकेशन है जो रीयल-टाइम के आस-पास, फ़ाइनेंशियल इंस्ट्रूमेंट का विश्लेषण करता है. जैसे, मुद्राएं, सामान्य स्टॉक, और ईटीएफ़. यह ऐप्लिकेशन, instruments कलेक्शन में इस तरह दस्तावेज़ लिखता है:

Node.js
async function insertData() {
  const instruments = [
    {
      symbol: 'AAA',
      price: {
        currency: 'USD',
        micros: 34790000
      },
      exchange: 'EXCHG1',
      instrumentType: 'commonstock',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.010Z'))
    },
    {
      symbol: 'BBB',
      price: {
        currency: 'JPY',
        micros: 64272000000
      },
      exchange: 'EXCHG2',
      instrumentType: 'commonstock',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.101Z'))
    },
    {
      symbol: 'Index1 ETF',
      price: {
        currency: 'USD',
        micros: 473000000
      },
      exchange: 'EXCHG1',
      instrumentType: 'etf',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.001Z'))
    }
  ];

  const batch = fs.batch();
  for (const inst of instruments) {
    const ref = fs.collection('instruments').doc();
    batch.set(ref, inst);
  }

  await batch.commit();
}

यह ऐप्लिकेशन, इन क्वेरी को चलाता है और timestamp फ़ील्ड के हिसाब से क्रम में लगाता है:

Node.js
function createQuery(fieldName, fieldOperator, fieldValue, limit = 5) {
  return fs.collection('instruments')
      .where(fieldName, fieldOperator, fieldValue)
      .orderBy('timestamp', 'desc')
      .limit(limit)
      .get();
}

function queryCommonStock() {
  return createQuery('instrumentType', '==', 'commonstock');
}

function queryExchange1Instruments() {
  return createQuery('exchange', '==', 'EXCHG1');
}

function queryUSDInstruments() {
  return createQuery('price.currency', '==', 'USD');
}
insertData()
    .then(() => {
      const commonStock = queryCommonStock()
          .then(
              (docs) => {
                console.log('--- queryCommonStock: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      const exchange1Instruments = queryExchange1Instruments()
          .then(
              (docs) => {
                console.log('--- queryExchange1Instruments: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      const usdInstruments = queryUSDInstruments()
          .then(
              (docs) => {
                console.log('--- queryUSDInstruments: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      return Promise.all([commonStock, exchange1Instruments, usdInstruments]);
    });

रिसर्च के बाद, आपको पता चलता है कि ऐप्लिकेशन को हर सेकंड 1,000 से 1,500 इंस्ट्रूमेंट अपडेट मिलेंगे. यह, इंडेक्स किए गए टाइमस्टैंप फ़ील्ड वाले दस्तावेज़ों के कलेक्शन के लिए, हर सेकंड 500 बार लिखने की अनुमति से ज़्यादा है. लिखने की थ्रूपुट बढ़ाने के लिए, आपको तीन शार्ड वैल्यू की ज़रूरत होगी. जैसे, MAX_INSTRUMENT_UPDATES/500 = 3. इस उदाहरण में, शार्ड वैल्यू के तौर पर x, y, और z का इस्तेमाल किया गया है. शार्ड वैल्यू के लिए, संख्याओं या अन्य वर्णों का भी इस्तेमाल किया जा सकता है.

शार्ड फ़ील्ड जोड़ना

अपने दस्तावेज़ों में shard फ़ील्ड जोड़ें. shard फ़ील्ड को x, y, या z वैल्यू पर सेट करें. इससे कलेक्शन पर, हर सेकंड 1,500 बार लिखने की सीमा लागू हो जाएगी.

Node.js
// Define our 'K' shard values
const shards = ['x', 'y', 'z'];
// Define a function to help 'chunk' our shards for use in queries.
// When using the 'in' query filter there is a max number of values that can be
// included in the value. If our number of shards is higher than that limit
// break down the shards into the fewest possible number of chunks.
function shardChunks() {
  const chunks = [];
  let start = 0;
  while (start < shards.length) {
    const elements = Math.min(MAX_IN_VALUES, shards.length - start);
    const end = start + elements;
    chunks.push(shards.slice(start, end));
    start = end;
  }
  return chunks;
}

// Add a convenience function to select a random shard
function randomShard() {
  return shards[Math.floor(Math.random() * Math.floor(shards.length))];
}
async function insertData() {
  const instruments = [
    {
      shard: randomShard(),  // add the new shard field to the document
      symbol: 'AAA',
      price: {
        currency: 'USD',
        micros: 34790000
      },
      exchange: 'EXCHG1',
      instrumentType: 'commonstock',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.010Z'))
    },
    {
      shard: randomShard(),  // add the new shard field to the document
      symbol: 'BBB',
      price: {
        currency: 'JPY',
        micros: 64272000000
      },
      exchange: 'EXCHG2',
      instrumentType: 'commonstock',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.101Z'))
    },
    {
      shard: randomShard(),  // add the new shard field to the document
      symbol: 'Index1 ETF',
      price: {
        currency: 'USD',
        micros: 473000000
      },
      exchange: 'EXCHG1',
      instrumentType: 'etf',
      timestamp: Timestamp.fromMillis(
          Date.parse('2019-01-01T13:45:23.001Z'))
    }
  ];

  const batch = fs.batch();
  for (const inst of instruments) {
    const ref = fs.collection('instruments').doc();
    batch.set(ref, inst);
  }

  await batch.commit();
}

शार्ड किए गए टाइमस्टैंप की क्वेरी करना

shard फ़ील्ड जोड़ने के लिए, आपको शार्ड किए गए नतीजों को एग्रीगेट करने के लिए, अपनी क्वेरी अपडेट करनी होंगी:

Node.js
function createQuery(fieldName, fieldOperator, fieldValue, limit = 5) {
  // For each shard value, map it to a new query which adds an additional
  // where clause specifying the shard value.
  return Promise.all(shardChunks().map(shardChunk => {
        return fs.collection('instruments')
            .where('shard', 'in', shardChunk)  // new shard condition
            .where(fieldName, fieldOperator, fieldValue)
            .orderBy('timestamp', 'desc')
            .limit(limit)
            .get();
      }))
      // Now that we have a promise of multiple possible query results, we need
      // to merge the results from all of the queries into a single result set.
      .then((snapshots) => {
        // Create a new container for 'all' results
        const docs = [];
        snapshots.forEach((querySnapshot) => {
          querySnapshot.forEach((doc) => {
            // append each document to the new all container
            docs.push(doc);
          });
        });
        if (snapshots.length === 1) {
          // if only a single query was returned skip manual sorting as it is
          // taken care of by the backend.
          return docs;
        } else {
          // When multiple query results are returned we need to sort the
          // results after they have been concatenated.
          // 
          // since we're wanting the `limit` newest values, sort the array
          // descending and take the first `limit` values. By returning negated
          // values we can easily get a descending value.
          docs.sort((a, b) => {
            const aT = a.data().timestamp;
            const bT = b.data().timestamp;
            const secondsDiff = aT.seconds - bT.seconds;
            if (secondsDiff === 0) {
              return -(aT.nanoseconds - bT.nanoseconds);
            } else {
              return -secondsDiff;
            }
          });
          return docs.slice(0, limit);
        }
      });
}

function queryCommonStock() {
  return createQuery('instrumentType', '==', 'commonstock');
}

function queryExchange1Instruments() {
  return createQuery('exchange', '==', 'EXCHG1');
}

function queryUSDInstruments() {
  return createQuery('price.currency', '==', 'USD');
}
insertData()
    .then(() => {
      const commonStock = queryCommonStock()
          .then(
              (docs) => {
                console.log('--- queryCommonStock: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      const exchange1Instruments = queryExchange1Instruments()
          .then(
              (docs) => {
                console.log('--- queryExchange1Instruments: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      const usdInstruments = queryUSDInstruments()
          .then(
              (docs) => {
                console.log('--- queryUSDInstruments: ');
                docs.forEach((doc) => {
                  console.log(`doc = ${util.inspect(doc.data(), {depth: 4})}`);
                });
              }
          );
      return Promise.all([commonStock, exchange1Instruments, usdInstruments]);
    });

इंडेक्स की परिभाषाएं अपडेट करना

हर सेकंड 500 बार लिखने की पाबंदी हटाने के लिए, मौजूदा सिंगल-फ़ील्ड और कंपोज़िट इंडेक्स मिटाएं. इनमें timestamp फ़ील्ड का इस्तेमाल किया जाता है.

कंपोज़िट इंडेक्स की परिभाषाएं मिटाना

Firebase कंसोल

  1. Firebase कंसोल में, Cloud Firestore कंपोज़िट इंडेक्स पेज खोलें.

    कंपोज़िट इंडेक्स पर जाएं

  2. timestamp फ़ील्ड वाले हर इंडेक्स के लिए, बटन पर क्लिक करें और मिटाएं पर क्लिक करें.

जीसीपी कंसोल

  1. Google Cloud Console में, डेटाबेस पेज पर जाएं.

    डेटाबेस पर जाएं

  2. डेटाबेस की सूची में से, ज़रूरी डेटाबेस चुनें.

  3. नेविगेशन मेन्यू में, इंडेक्स पर क्लिक करें. इसके बाद, कंपोज़िट टैब पर क्लिक करें.

  4. फ़िल्टर करें फ़ील्ड का इस्तेमाल करके, इंडेक्स की परिभाषाएं खोजें जिनमें timestamp फ़ील्ड शामिल है.

  5. इनमें से हर इंडेक्स के लिए, बटन पर क्लिक करें और मिटाएं पर क्लिक करें.

Firebase CLI

  1. अगर आपने Firebase CLI सेट अप नहीं किया है, तो इंस्टॉल करने के लिए यह तरीका अपनाएं CLI और firebase init कमांड चलाएं. init कमांड के दौरान, पक्का करें कि आपने Firestore: Deploy rules and create indexes for Firestore को चुना हो.
  2. सेटअप के दौरान, Firebase CLI, मौजूदा इंडेक्स की परिभाषाओं को डाउनलोड करके, डिफ़ॉल्ट रूप से firestore.indexes.json नाम की फ़ाइल में सेव करता है.
  3. ऐसी सभी इंडेक्स की परिभाषाएं हटाएं जिनमें timestamp फ़ील्ड शामिल है. उदाहरण के लिए:

    {
    "indexes": [
      // Delete composite index definition that contain the timestamp field
      {
        "collectionGroup": "instruments",
        "queryScope": "COLLECTION",
        "fields": [
          {
            "fieldPath": "exchange",
            "order": "ASCENDING"
          },
          {
            "fieldPath": "timestamp",
            "order": "DESCENDING"
          }
        ]
      },
      {
        "collectionGroup": "instruments",
        "queryScope": "COLLECTION",
        "fields": [
          {
            "fieldPath": "instrumentType",
            "order": "ASCENDING"
          },
          {
            "fieldPath": "timestamp",
            "order": "DESCENDING"
          }
        ]
      },
      {
        "collectionGroup": "instruments",
        "queryScope": "COLLECTION",
        "fields": [
          {
            "fieldPath": "price.currency",
            "order": "ASCENDING"
          },
          {
            "fieldPath": "timestamp",
            "order": "DESCENDING"
          }
        ]
      },
     ]
    }
    
  4. इंडेक्स की अपडेट की गई परिभाषाएं डिप्लॉय करें:

    firebase deploy --only firestore:indexes
    

सिंगल-फ़ील्ड इंडेक्स की परिभाषाएं अपडेट करना

Firebase कंसोल

  1. Firebase कंसोल में, Cloud Firestore सिंगल-फ़ील्ड इंडेक्स पेज खोलें.

    सिंगल-फ़ील्ड इंडेक्स पर जाएं

  2. छूट जोड़ें पर क्लिक करें.

  3. कलेक्शन आईडी में, instruments डालें. फ़ील्ड पाथ में, timestamp डालें.

  4. क्वेरी स्कोप में, कलेक्शन और कलेक्शन ग्रुप दोनों को चुनें.

  5. अगला पर क्लिक करें

  6. इंडेक्स की सभी सेटिंग को टॉगल करके बंद पर सेट करें. सेव करें पर क्लिक करें.

  7. shard फ़ील्ड के लिए भी यही तरीका अपनाएं.

जीसीपी कंसोल

  1. Google Cloud Console में, डेटाबेस पेज पर जाएं.

    डेटाबेस पर जाएं

  2. डेटाबेस की सूची में से, ज़रूरी डेटाबेस चुनें.

  3. नेविगेशन मेन्यू में, इंडेक्स पर क्लिक करें. इसके बाद, सिंगल-फ़ील्ड टैब पर क्लिक करें.

  4. सिंगल-फ़ील्ड टैब पर क्लिक करें.

  5. छूट जोड़ें पर क्लिक करें.

  6. कलेक्शन आईडी में, instruments डालें. फ़ील्ड पाथ में, timestamp डालें.

  7. क्वेरी स्कोप में, कलेक्शन और कलेक्शन ग्रुप दोनों को चुनें.

  8. अगला पर क्लिक करें

  9. इंडेक्स की सभी सेटिंग को टॉगल करके बंद पर सेट करें. सेव करें पर क्लिक करें.

  10. shard फ़ील्ड के लिए भी यही तरीका अपनाएं.

Firebase CLI

  1. इंडेक्स की परिभाषाओं वाली फ़ाइल के fieldOverrides सेक्शन में, यह जानकारी जोड़ें:

    {
     "fieldOverrides": [
       // Disable single-field indexing for the timestamp field
       {
         "collectionGroup": "instruments",
         "fieldPath": "timestamp",
         "indexes": []
       },
     ]
    }
    
  2. इंडेक्स की अपडेट की गई परिभाषाएं डिप्लॉय करें:

    firebase deploy --only firestore:indexes
    

नए कंपोज़िट इंडेक्स बनाना

timestamp वाले सभी पुराने इंडेक्स हटाने के बाद, वे नए इंडेक्स तय करें जिनकी आपके ऐप्लिकेशन को ज़रूरत है. timestamp फ़ील्ड वाले किसी भी इंडेक्स में, shard फ़ील्ड भी शामिल होना चाहिए. उदाहरण के लिए, ऊपर दी गई क्वेरी के लिए, ये इंडेक्स जोड़ें:

कलेक्शन इंडेक्स किए गए फ़ील्ड क्वेरी स्कोप
instruments shard, price.currency, timestamp कलेक्शन
instruments shard, exchange, timestamp कलेक्शन
instruments shard, instrumentType, timestamp कलेक्शन

गड़बड़ी के मैसेज

अपडेट की गई क्वेरी चलाकर, इन इंडेक्स को बनाया जा सकता है.

हर क्वेरी, गड़बड़ी का एक मैसेज दिखाती है. इसमें Firebase कंसोल में, ज़रूरी इंडेक्स बनाने का लिंक भी शामिल होता है.

Firebase CLI

  1. इंडेक्स की परिभाषाओं वाली फ़ाइल में, ये इंडेक्स जोड़ें:

     {
       "indexes": [
       // New indexes for sharded timestamps
         {
           "collectionGroup": "instruments",
           "queryScope": "COLLECTION",
           "fields": [
             {
               "fieldPath": "shard",
               "order": "DESCENDING"
             },
             {
               "fieldPath": "exchange",
               "order": "ASCENDING"
             },
             {
               "fieldPath": "timestamp",
               "order": "DESCENDING"
             }
           ]
         },
         {
           "collectionGroup": "instruments",
           "queryScope": "COLLECTION",
           "fields": [
             {
               "fieldPath": "shard",
               "order": "DESCENDING"
             },
             {
               "fieldPath": "instrumentType",
               "order": "ASCENDING"
             },
             {
               "fieldPath": "timestamp",
               "order": "DESCENDING"
             }
           ]
         },
         {
           "collectionGroup": "instruments",
           "queryScope": "COLLECTION",
           "fields": [
             {
               "fieldPath": "shard",
               "order": "DESCENDING"
             },
             {
               "fieldPath": "price.currency",
               "order": "ASCENDING"
             },
             {
               "fieldPath": "timestamp",
               "order": "DESCENDING"
             }
           ]
         },
       ]
     }
    
  2. इंडेक्स की अपडेट की गई परिभाषाएं डिप्लॉय करें:

    firebase deploy --only firestore:indexes
    

क्रम से इंडेक्स किए गए फ़ील्ड के लिए, लिखने की सीमा को समझना

क्रम से इंडेक्स किए गए फ़ील्ड के लिए, लिखने की दर पर लगी सीमा की वजह यह है कि Cloud Firestore इंडेक्स की वैल्यू कैसे सेव करता है और इंडेक्स को लिखने की प्रोसेस को कैसे स्केल करता है. इंडेक्स में लिखने की हर प्रोसेस के लिए, Cloud Firestore एक कुंजी-वैल्यू एंट्री तय करता है. इसमें दस्तावेज़ का नाम और इंडेक्स किए गए हर फ़ील्ड की वैल्यू को जोड़ा जाता है. Cloud Firestore इंडेक्स की इन एंट्री को डेटा के ग्रुप में व्यवस्थित करता है. इन्हें टैबलेट कहा जाता है. हर Cloud Firestore सर्वर में एक या उससे ज़्यादा टैबलेट होते हैं. जब किसी टैबलेट पर लिखने का लोड बहुत ज़्यादा हो जाता है, तो Cloud Firestore टैबलेट को छोटे-छोटे टैबलेट में बांटकर और नए टैबलेट को अलग-अलग Cloud Firestore सर्वर पर फैलाकर, हॉरिज़ॉन्टली स्केल करता है.

Cloud Firestore लेक्सिकोग्राफ़िक तौर पर एक जैसी इंडेक्स एंट्री को एक ही टैबलेट पर रखता है. अगर किसी टैबलेट में इंडेक्स की वैल्यू बहुत ज़्यादा एक जैसी हैं, तो Cloud Firestore टैबलेट को छोटे-छोटे टैबलेट में नहीं बांट सकता. जैसे, टाइमस्टैंप फ़ील्ड के लिए. इससे एक हॉट स्पॉट बनता है, जहां एक ही टैबलेट को बहुत ज़्यादा ट्रैफ़िक मिलता है. साथ ही, हॉट स्पॉट पर पढ़ने और लिखने की कार्रवाइयां धीमी हो जाती हैं.

टाइमस्टैंप फ़ील्ड को शार्ड करके, Cloud Firestore के लिए कई टैबलेट पर वर्कलोड को कुशलता से बांटना मुमकिन हो जाता है. हालांकि, टाइमस्टैंप फ़ील्ड की वैल्यू एक जैसी बनी रह सकती हैं. लेकिन शार्ड और इंडेक्स वैल्यू को जोड़ने से, Cloud Firestore को इंडेक्स एंट्री के बीच इतना स्पेस मिल जाता है कि वह एंट्री को कई टैबलेट में बांट सके.

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