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

मैं शुरुआत से वादा श्रृंखला को सशर्त रूप से कैसे पुनः आरंभ करूं?

संक्षेप में, आपको वास्तव में इस मामले में ऐसा करने की आवश्यकता नहीं है। लेकिन एक लंबी व्याख्या है।

यदि आपका MongoDB संस्करण इसका समर्थन करता है, तो आप बस का उपयोग कर सकते हैं। $नमूना "यादृच्छिक" चयन प्राप्त करने के लिए आपकी प्रारंभिक क्वेरी शर्तों के बाद एकत्रीकरण पाइपलाइन।

बेशक किसी भी मामले में, अगर कोई पात्र नहीं है क्योंकि वे पहले से ही "जीत गए" हैं तो बस उन्हें इस तरह चिह्नित करें, या तो सीधे सारणीबद्ध परिणामों के दूसरे सेट में। लेकिन यहां "बहिष्करण" का सामान्य मामला संभावित परिणामों से "विजेताओं" को बाहर करने के लिए केवल क्वेरी को संशोधित करना है।

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

const MongoClient = require('mongodb').MongoClient,
      whilst = require('async').whilst,
      BPromise = require('bluebird');

const users = [
  'Bill',
  'Ted',
  'Fred',
  'Fleur',
  'Ginny',
  'Harry'
];

function log (data) {
  console.log(JSON.stringify(data,undefined,2))
}

const oneHour = ( 1000 * 60 * 60 );

(async function() {

  let db;

  try {
    db = await MongoClient.connect('mongodb://localhost/raffle');

    const collection = db.collection('users');

    // Clean data
    await collection.remove({});

    // Insert some data
    let inserted = await collection.insertMany(
      users.map( name =>
        Object.assign({ name },
          ( name !== 'Harry' )
            ? { updated: new Date() }
            : { updated: new Date( new Date() - (oneHour * 2) ) }
        )
      )
    );
    log(inserted);

    // Loop with aggregate $sample
    console.log("Aggregate $sample");

    while (true) {
      let winner = (await collection.aggregate([
        { "$match": {
          "updated": {
            "$gte": new Date( new Date() - oneHour ),
            "$lt": new Date()
          },
          "isWinner": { "$ne": true }
        }},
        { "$sample": { "size": 1 } }
      ]).toArray())[0];

      if ( winner !== undefined ) {
        log(winner);    // Picked winner
        await collection.update(
          { "_id": winner._id },
          { "$set": { "isWinner": true } }
        );
        continue;
      }
      break;
    }

    // Reset data state
    await collection.updateMany({},{ "$unset": { "isWinner": "" } });

    // Loop with random length
    console.log("Math random selection");
    while (true) {
      let winners = await collection.find({
        "updated": {
          "$gte": new Date( new Date() - oneHour ),
          "$lt": new Date()
        },
        "isWinner": { "$ne": true }
      }).toArray();

      if ( winners.length > 0 ) {
        let winner = winners[Math.floor(Math.random() * winners.length)];
        log(winner);
        await collection.update(
          { "_id": winner._id },
          { "$set": { "isWinner": true } }
        );
        continue;
      }
      break;
    }

    // Reset data state
    await collection.updateMany({},{ "$unset": { "isWinner": "" } });

    // Loop async.whilst
    console.log("async.whilst");

    // Wrap in a promise to await
    await new Promise((resolve,reject) => {
      var looping = true;
      whilst(
        () => looping,
        (callback) => {
          collection.find({
            "updated": {
              "$gte": new Date( new Date() - oneHour ),
              "$lt": new Date()
            },
            "isWinner": { "$ne": true }
          })
          .toArray()
          .then(winners => {
            if ( winners.length > 0 ) {
              let winner = winners[Math.floor(Math.random() * winners.length)];
              log(winner);
              return collection.update(
                { "_id": winner._id },
                { "$set": { "isWinner": true } }
              );
            } else {
              looping = false;
              return
            }
          })
          .then(() => callback())
          .catch(err => callback(err))
        },
        (err) => {
          if (err) reject(err);
          resolve();
        }
      );
    });

    // Reset data state
    await collection.updateMany({},{ "$unset": { "isWinner": "" } });

    // Or synatax for Bluebird coroutine where no async/await
    console.log("Bluebird coroutine");

    await BPromise.coroutine(function* () {
      while(true) {
        let winners = yield collection.find({
          "updated": {
            "$gte": new Date( new Date() - oneHour ),
            "$lt": new Date()
          },
          "isWinner": { "$ne": true }
        }).toArray();

        if ( winners.length > 0 ) {
          let winner = winners[Math.floor(Math.random() * winners.length)];
          log(winner);
          yield collection.update(
            { "_id": winner._id },
            { "$set": { "isWinner": true } }
          );
          continue;
        }
        break;
      }
    })();

  } catch(e) {
    console.error(e)
  } finally {
    db.close()
  }
})()

और निश्चित रूप से किसी भी दृष्टिकोण के साथ परिणाम हर बार यादृच्छिक होते हैं और पिछले "विजेताओं" को वास्तविक क्वेरी में ही चयन से बाहर रखा जाता है। यहां "लूप ब्रेक" का उपयोग केवल परिणामों को आउटपुट करने के लिए किया जाता है जब तक कि कोई और संभावित विजेता न हो।

"लूप ब्रेकिंग" विधियों पर एक नोट

आधुनिक नोड.जेएस परिवेशों में सामान्य अनुशंसा को async/await/yield में बनाया जाना चाहिए सुविधाओं को अब v8.x.x रिलीज़ में डिफ़ॉल्ट रूप से चालू के रूप में शामिल किया गया है। ये संस्करण इस साल अक्टूबर में (लेखन के रूप में) और मेरे अपने व्यक्तिगत "तीन महीने के नियम" के अनुसार दीर्घकालिक समर्थन (एलटीएस) को प्रभावित करेंगे, फिर कोई भी नया काम उन चीजों पर आधारित होना चाहिए जो उस समय वर्तमान में होंगे।

यहां वैकल्पिक मामले async.await के माध्यम से प्रस्तुत किए गए हैं एक अलग पुस्तकालय निर्भरता के रूप में। या अन्यथा "ब्लूबर्ड" Promise.coroutine , बाद वाला मामला यह है कि आप वैकल्पिक रूप से Promise.try , लेकिन यदि आप उस फ़ंक्शन को प्राप्त करने के लिए एक पुस्तकालय शामिल करने जा रहे हैं, तो आप अन्य फ़ंक्शन का भी उपयोग कर सकते हैं जो अधिक आधुनिक वाक्यविन्यास दृष्टिकोण को लागू करता है।

तो "एक वादा/कॉलबैक तोड़ना" प्रदर्शित करते हुए "जबकि" (सजा का इरादा नहीं है) लूप, मुख्य बात जो वास्तव में यहां से हटा दी जानी चाहिए वह अलग क्वेरी प्रक्रिया है, जो वास्तव में "बहिष्करण" करती है जिसे "लूप" में लागू करने का प्रयास किया जा रहा था जब तक कि यादृच्छिक विजेता का चयन नहीं किया गया था।

वास्तविक मामला यह है कि डेटा इसे सबसे अच्छा निर्धारित करता है। लेकिन पूरा उदाहरण कम से कम ऐसे तरीके दिखाता है कि चयन और "लूप ब्रेक" दोनों को लागू किया जा सकता है।




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. mongodb schema.createIndex एक फ़ंक्शन नहीं है

  2. रेडिस कब? मोंगोडीबी कब?

  3. डेटा खोए बिना मैं एक मोंगोडब कैप्ड संग्रह का आकार कैसे बदल सकता हूं?

  4. ES6 टेम्पलेट स्ट्रिंग के साथ MongoDB ऑब्जेक्ट कुंजी

  5. MongoDB GUI क्लाइंट (क्रॉस-प्लेटफ़ॉर्म या Linux)

© कॉपीराइट http://hi.sqldat.com सर्वाधिकार सुरक्षित