MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Iterasi Kursor Asinkron dengan Sub-tugas Asinkron

Cursor.hasNext() metode ini juga "asinkron", jadi Anda perlu await itu juga. Hal yang sama berlaku untuk Cursor.next() . Oleh karena itu penggunaan "loop" yang sebenarnya harus menjadi 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
  }

}

Seperti dicatat dalam komentar, akhirnya Cursor.hasNext() akan mengembalikan false ketika kursor benar-benar habis, dan Cursor.next() adalah hal yang sebenarnya mengambil setiap nilai dari kursor. Anda dapat melakukan struktur lain dan break loop ketika hasNext() adalah false , tetapi secara lebih alami cocok untuk while .

Ini masih "async", jadi Anda harus await resolusi janji pada masing-masing, dan itulah fakta utama yang Anda lewatkan.

Adapun Cursor.map() , maka Anda mungkin kehilangan poin yang dapat ditandai dengan async tandai juga fungsi yang disediakan:

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

Tetapi Anda sebenarnya masih ingin "mengulangi" itu di suatu tempat, kecuali jika Anda dapat menggunakan .pipe() ke beberapa tujuan keluaran lainnya.

Juga async/await flag juga membuat Cursor.forEach() "lebih praktis lagi" , karena salah satu kelemahan umum adalah tidak dapat dengan mudah menangani panggilan asinkron "dalam", tetapi dengan tanda ini Anda sekarang dapat melakukannya dengan mudah, meskipun harus diakui karena Anda harus gunakan panggilan balik, Anda mungkin ingin membungkus ini dengan Janji :

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();
    }
  )
);

Tentu saja selalu ada cara untuk menerapkan ini baik dengan panggilan balik atau implementasi Janji biasa, tetapi ini adalah "gula" dari async/await daripada benar-benar membuat ini terlihat jauh lebih bersih.

NodeJS v10.x dan driver MongoDB Node 3.1.x dan yang lebih baru

Dan versi favorit menggunakan AsyncIterator yang sekarang diaktifkan di NodeJS v10 dan lebih tinggi. Ini cara yang jauh lebih bersih untuk beralih

async function dbanalyze(){

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

Yang mana "dengan cara" kembali ke pertanyaan awal tentang penggunaan for loop karena kita dapat melakukan for-await-of sintaks di sini kedepan mendukung iterable yang mendukung antarmuka yang benar. Dan Cursor mendukung antarmuka ini.

Jika Anda penasaran, inilah daftar yang saya buat beberapa waktu lalu untuk mendemonstrasikan berbagai teknik iterasi kursor. Bahkan termasuk kasus untuk Async Iterators dari fungsi generator:

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. Indeks Senyawa Tiga Mongo

  2. Menyimpan Enum sebagai string di MongoDB

  3. Bagaimana cara mendapatkan semua hasil jika bidang bersantai tidak ada di mongodb

  4. kueri grup mongo cara menyimpan bidang

  5. Grup dan sortir Mongodb