MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

अतुल्यकालिक उप-कार्य के साथ Async कर्सर पुनरावृत्ति

Cursor.hasNext() विधि भी "एसिंक्रोनस" है, इसलिए आपको await . करने की आवश्यकता है वह भी। वही Cursor.next() . के लिए जाता है . इसलिए वास्तविक "लूप" उपयोग वास्तव में while होना चाहिए :

async function dbanalyze(){

  let cursor = db.collection('randomcollection').find()
  while ( await cursor.hasNext() ) {  // will return false when there are no more results
    let doc = await cursor.next();    // actually gets the document
    // do something, possibly async with the current document
  }

}

जैसा कि टिप्पणियों में बताया गया है, अंततः Cursor.hasNext() false लौटाएगा जब कर्सर वास्तव में समाप्त हो जाता है, और Cursor.next() वह चीज है जो वास्तव में कर्सर से प्रत्येक मान को पुनः प्राप्त कर रही है। आप अन्य संरचनाएं कर सकते हैं और break कर सकते हैं लूप जब hasNext() false है , लेकिन यह अधिक स्वाभाविक रूप से एक while . के लिए उधार देता है ।

ये अभी भी "async" हैं, इसलिए आपको await . करने की आवश्यकता है प्रत्येक पर वादा संकल्प, और यही वह मुख्य तथ्य था जिसे आप याद कर रहे थे।

जहां तक ​​Cursor.map() का सवाल है? , तो आप शायद इस बिंदु को याद कर रहे हैं कि इसे async . से चिह्नित किया जा सकता है दिए गए फ़ंक्शन पर भी फ़्लैग करें:

 cursor.map( async doc => {                   // We can mark as async
    let newDoc = await someAsyncMethod(doc);  // so you can then await inside
    return newDoc;
 })

लेकिन आप अभी भी वास्तव में कहीं न कहीं "पुनरावृत्ति" करना चाहते हैं, जब तक कि आप .pipe() का उपयोग करके दूर नहीं हो सकते किसी अन्य आउटपुट गंतव्य के लिए।

साथ ही async/await झंडे भी बनाते हैं Cursor.forEach() "फिर से अधिक व्यावहारिक" , क्योंकि यह एक सामान्य दोष है कि केवल "आंतरिक" एसिंक्रोनस कॉल को संभालने में सक्षम नहीं हो रहा था, लेकिन इन झंडों के साथ अब आप इसे आसानी से कर सकते हैं, हालांकि माना जाता है कि आपको जरूरी कॉलबैक का उपयोग करें, आप शायद इसे एक वादे में लपेटना चाहते हैं:

await new Promise((resolve, reject) => 
  cursor.forEach(
    async doc => {                              // marked as async
      let newDoc = await someAsyncMethod(doc);  // so you can then await inside
      // do other things
    },
    err => {
      // await was respected, so we get here when done.
      if (err) reject(err);
      resolve();
    }
  )
);

बेशक कॉलबैक या सादे वादा कार्यान्वयन के साथ इसे लागू करने के तरीके हमेशा रहे हैं, लेकिन यह async/await की "चीनी" है की तुलना में यह वास्तव में अधिक साफ दिखता है।

NodeJS v10.x और MongoDB नोड ड्राइवर 3.1.x और ऊपर

और पसंदीदा संस्करण AsyncIterator . का उपयोग करता है जो अब NodeJS v10 और ऊपर में सक्षम है। यह पुनरावृति करने का अधिक स्वच्छ तरीका है

async function dbanalyze(){

  let cursor = db.collection('randomcollection').find()
  for await ( let doc of cursor ) {
    // do something with the current document
  }    
}

जो "एक तरह से" for . का उपयोग करने के संबंध में मूल रूप से पूछे गए प्रश्न पर वापस आता है लूप क्योंकि हम for-await-of कर सकते हैं सिंटैक्स यहाँ चलने योग्य का समर्थन करता है जो सही इंटरफ़ेस का समर्थन करता है। और Cursor इस इंटरफ़ेस का समर्थन करता है।

यदि आप जिज्ञासु हैं, तो यहां एक सूची है जिसे मैंने कुछ समय पहले विभिन्न कर्सर पुनरावृत्ति तकनीकों को प्रदर्शित करने के लिए तैयार किया था। इसमें जनरेटर फ़ंक्शन से Async Iterators के लिए एक केस भी शामिल है:

const Async = require('async'),
      { MongoClient, Cursor } = require('mongodb');

const testLen = 3;
(async function() {

  let db;

  try {
    let client = await MongoClient.connect('mongodb://localhost/');

    let db = client.db('test');
    let collection = db.collection('cursortest');

    await collection.remove();

    await collection.insertMany(
      Array(testLen).fill(1).map((e,i) => ({ i }))
    );

    // Cursor.forEach
    console.log('Cursor.forEach');
    await new Promise((resolve,reject) => {
      collection.find().forEach(
        console.log,
        err => {
          if (err) reject(err);
          resolve();
        }
      );
    });

    // Async.during awaits cursor.hasNext()
    console.log('Async.during');
    await new Promise((resolve,reject) => {

      let cursor = collection.find();

      Async.during(
        (callback) => Async.nextTick(() => cursor.hasNext(callback)),
        (callback) => {
          cursor.next((err,doc) => {
            if (err) callback(err);
            console.log(doc);
            callback();
          })
        },
        (err) => {
          if (err) reject(err);
          resolve();
        }
      );

    });

    // async/await allows while loop
    console.log('async/await while');
    await (async function() {

      let cursor = collection.find();

      while( await cursor.hasNext() ) {
        let doc = await cursor.next();
        console.log(doc);
      }

    })();

    // await event stream
    console.log('Event Stream');
    await new Promise((end,error) => {
      let cursor = collection.find();

      for ( let [k,v] of Object.entries({ end, error, data: console.log }) )
        cursor.on(k,v);
    });

    // Promise recursion
    console.log('Promise recursion');
    await (async function() {

      let cursor = collection.find();

      function iterate(cursor) {
        return cursor.hasNext().then( bool =>
          (bool) ? cursor.next().then( doc => {
            console.log(doc);
            return iterate(cursor);
          }) : Promise.resolve()
        )
      }

      await iterate(cursor);

    })();

    // Uncomment if node is run with async iteration enabled
    // --harmony_async_iteration


    console.log('Generator Async Iterator');
    await (async function() {

      async function* cursorAsyncIterator() {
        let cursor = collection.find();

        while (await cursor.hasNext() ) {
          yield cursor.next();
        }

      }

      for await (let doc of cursorAsyncIterator()) {
        console.log(doc);
      }

    })();


    // This is supported with Node v10.x and the 3.1 Series Driver
    await (async function() {

      for await (let doc of collection.find()) {
        console.log(doc);
      }

    })();

    client.close();

  } catch(e) {
    console.error(e);
  } finally {
    process.exit();
  }

})();



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Amazon EC2 पर MongoDB को तैनात करने के लिए 6 सर्वोत्तम अभ्यास

  2. मैं बिना समय के मोंगोइड/रेल का उपयोग करके मोंगोडब से कैसे पूछ सकता हूं?

  3. फ़ाइल आयात करके MongoDB दस्तावेज़ कैसे हटाएं

  4. MongoDB के एकत्रीकरण ढांचे के साथ चलती औसत?

  5. MongoDB में एक संग्रह कॉपी/क्लोन करें