कैसे एक MongoDB संग्रह में परिवर्तन के लिए सुनने के लिए?


200

मैं डेटा स्टोर के रूप में MongoDB के साथ एक प्रकार की पृष्ठभूमि नौकरी कतार प्रणाली बना रहा हूं। मैं नौकरी की प्रक्रिया के लिए श्रमिकों को स्पॉन्ग करने से पहले एक मोंगोबीडी संग्रह में आवेषण के लिए "सुन" कैसे सकता हूं? क्या मुझे यह देखने के लिए हर कुछ सेकंड में पोल ​​करने की ज़रूरत है कि क्या पिछली बार से कोई बदलाव हुआ है, या कोई तरीका है जिससे मेरी स्क्रिप्ट आवेषण के लिए प्रतीक्षा कर सकती है? यह एक PHP प्रोजेक्ट है जिस पर मैं काम कर रहा हूं, लेकिन रूबी या भाषा अज्ञेय में जवाब देने के लिए स्वतंत्र महसूस करता हूं।


1
आपके परिदृश्य को संबोधित करने के लिए MongoDB 3.6 में परिवर्तन धाराएँ जोड़ी गईं। docs.mongodb.com/manual/changeStreams यदि आप MongoDB Atlas का उपयोग कर रहे हैं, तो भी आप Stitch Triggers का लाभ उठा सकते हैं, जो आपको सम्मिलित / अपडेट / डिलीट / आदि के जवाब में फ़ंक्शन निष्पादित करने की अनुमति देता है। docs.mongodb.com/stitch/triggers/overview अफीम को पार्स करने के लिए और अधिक की आवश्यकता नहीं है।
रॉबर्ट वाल्टर्स 12

जवाबों:


111

क्या आप लगता है बहुत ट्रिगर की तरह लग रहा है। MongoDB में ट्रिगर्स के लिए कोई समर्थन नहीं है, हालांकि कुछ लोगों ने कुछ तरकीबों का उपयोग करके "अपने स्वयं के रोल किए हैं"। यहाँ कुंजी oplog है।

जब आप एक रेप्लिका सेट में MongoDB चलाते हैं, तो MongoDB की सभी कार्रवाइयाँ एक ऑपरेशन लॉग में लॉग की जाती हैं (जिसे oplog के रूप में जाना जाता है)। ओप्लोग मूल रूप से डेटा में किए गए संशोधनों की एक चल सूची है। रेप्लिकास इस ओप्‍लोग पर बदलावों को सुनकर और फिर स्‍थानीय रूप से परिवर्तनों को लागू करके कार्य करता है।

क्या यह ध्वनि परिचित है?

मैं यहां पूरी प्रक्रिया का विवरण नहीं दे सकता, यह प्रलेखन के कई पृष्ठ हैं, लेकिन आपके लिए आवश्यक उपकरण उपलब्ध हैं।

पहले ऑपोगल पर कुछ राइट-अप - संक्षिप्त विवरण - संग्रह का लेआउटlocal (जिसमें ओप्लोग शामिल हैं)

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


1
हम्म ... बिल्कुल नहीं, जो मेरे मन में था। मैं इस बिंदु पर केवल एक उदाहरण चला रहा हूं (कोई दास नहीं)। तो शायद एक अधिक बुनियादी समाधान?
एंड्रयू

17
आप --replSetविकल्प के साथ सर्वर शुरू कर सकते हैं और यह / को पॉप्युलेट करेगा oplog। माध्यमिक के बिना भी। यह निश्चित रूप से डीबी में परिवर्तन को "सुनने" का एकमात्र तरीका है।
गेट्स वीपी

2
: यह एक अच्छा स्थानीय स्तर पर डीबी में परिवर्तन प्रवेश करने के लिए कैसे सेटअप oplog को वर्णन है loosexaml.wordpress.com/2012/09/03/...
johndodo

Cooooool! मैं वास्तव में यही चाहता हूं। और मुझे npm पर 'mongo-oplog' नाम की एक लाइब्रेरी मिली। इतना खुश ~
pjincz

मैं इस उत्तर को लिखने के समय से सहमत हूं कि ट्रिगर उपलब्ध नहीं हो सकता है, लेकिन यहां जो सभी के लिए है, अब एक विकल्प उपलब्ध है, MongoDB Stitch ( docs.mongodb.com/stitch/#stitch ) और Stitch ट्रिगर ( डॉक्स) देखें। mongodb.com/stitch/triggers ) ..
whoami

102

MongoDB में क्या कहा जाता है capped collectionsऔर tailable cursorsयह MongoDB श्रोताओं को डेटा पुश करने की अनुमति देता है।

capped collectionअनिवार्य रूप से एक संग्रह है जो एक निश्चित आकार है और केवल सम्मिलन की अनुमति देता है। यहाँ यह है कि यह एक बनाने के लिए कैसा लगेगा:

db.createCollection("messages", { capped: true, size: 100000000 })

मोंगोबीडी टाबेल कर्सर्स ( जोनाथन एच। वेज द्वारा मूल पोस्ट )

माणिक

coll = db.collection('my_collection')
cursor = Mongo::Cursor.new(coll, :tailable => true)
loop do
  if doc = cursor.next_document
    puts doc
  else
    sleep 1
  end
end

पीएचपी

$mongo = new Mongo();
$db = $mongo->selectDB('my_db')
$coll = $db->selectCollection('my_collection');
$cursor = $coll->find()->tailable(true);
while (true) {
    if ($cursor->hasNext()) {
        $doc = $cursor->getNext();
        print_r($doc);
    } else {
        sleep(1);
    }
}

अजगर ( रॉबर्ट स्टीवर्ट द्वारा )

from pymongo import Connection
import time

db = Connection().my_db
coll = db.my_collection
cursor = coll.find(tailable=True)
while cursor.alive:
    try:
        doc = cursor.next()
        print doc
    except StopIteration:
        time.sleep(1)

पर्ल ( मैक्स द्वारा )

use 5.010;

use strict;
use warnings;
use MongoDB;

my $db = MongoDB::Connection->new;
my $coll = $db->my_db->my_collection;
my $cursor = $coll->find->tailable(1);
for (;;)
{
    if (defined(my $doc = $cursor->next))
    {
        say $doc;
    }
    else
    {
        sleep 1;
    }
}

अतिरिक्त संसाधन:

Ruby / Node.js ट्यूटोरियल जो एक MongoDB कैप संग्रह में आवेषण सुनता है एक एप्लिकेशन बनाने के माध्यम से चलता है।

एक लेख में और अधिक विस्तार से जहरीले अभिशापों के बारे में बात की गई है।

पीएचपी, रूबी, पायथन, और टटल कॉर्सर्स का उपयोग करने के पर्ल उदाहरण।


70
1 सो जाओ? वास्तव में? उत्पादन कोड के लिए? वह मतदान कैसे नहीं है?
आरबीपी

2
@ आरबीपी हाहा, मैंने कभी नहीं कहा कि यह उत्पादन कोड था, लेकिन आप सही हैं, एक सेकंड के लिए सोना एक अच्छा अभ्यास नहीं है। मुझे यकीन है कि मुझे वह उदाहरण कहीं और से मिला है। हालांकि यह कैसे refactor करने के लिए सुनिश्चित नहीं है।
एंड्रयू

14
@kroe क्योंकि उन अप्रासंगिक विवरणों को नए प्रोग्रामर द्वारा उत्पादन कोड में डाल दिया जाएगा जो समझ नहीं सकते कि यह क्यों बुरा है।
कैटफ़िश

3
मैं आपकी बात समझता हूं, लेकिन कुछ नए प्रोग्रामर्स से "स्लीप 1" को प्रोडक्शन में जोड़ने की उम्मीद करना लगभग आपत्तिजनक है! मेरा मतलब है, मुझे आश्चर्य नहीं होगा ... लेकिन अगर कोई इसे उत्पादन में रखता है, तो कम से कम कठिन तरीके से और हमेशा के लिए सीख जाएगा .. हाहा
क्रोई

19
उत्पादन में time.sleep (1) करने में क्या गलत है?
अल जोहरी

44

चूंकि MongoDB 3.6 में चेंज स्ट्रीम नामक एक नया नोटिफिकेशन एपीआई होगा जिसे आप इसके लिए उपयोग कर सकते हैं। एक उदाहरण के लिए इस ब्लॉग पोस्ट को देखें । इससे उदाहरण:

cursor = client.my_db.my_collection.changes([
    {'$match': {
        'operationType': {'$in': ['insert', 'replace']}
    }},
    {'$match': {
        'newDocument.n': {'$gte': 1}
    }}
])

# Loops forever.
for change in cursor:
    print(change['newDocument'])

4
क्यों? क्या आप विस्तार से समझा सकते हैं? यह अब मानक तरीका है?
मेराथ

1
कैसे? मतदान का उपयोग न करें - आपको छोरों आदि के बजाय एक व्यवस्थित दृष्टिकोण की आवश्यकता है
अलेक्जेंडर मिल्स

3
आप यहाँ मतदान कहाँ देखते हैं?
मेराट

मुझे लगता है कि वह आखिरी लूप की बात कर रहे हैं। लेकिन मुझे लगता है कि PyMongo केवल उसी का समर्थन करता है। मोटर में एक async / घटना श्रोता-शैली कार्यान्वयन हो सकता है।
शेन ह्सू

41

इसे देखें: धाराएँ बदलें

10 जनवरी, 2018 - 3.6 जारी करें

* EDIT: मैंने इस बारे में एक लेख लिखा कि यह कैसे किया जाए https://medium.com/riow/mongodb-data-collection-change-85b63d96ff76

https://docs.mongodb.com/v3.6/changeStreams/


यह मोंगोडब में नया है 3.6 https://docs.mongodb.com/manual/release-notes/3.6/ 2018/01/10

$ mongod --version
db version v3.6.2

चेंजस्ट्रीम का उपयोग करने के लिए डेटाबेस में एक प्रतिकृति सेट होना चाहिए

प्रतिकृति सेट के बारे में अधिक जानकारी: https://docs.mongodb.com/manual/replication/

आपका डेटाबेस डिफ़ॉल्ट रूप से " स्टैंडअलोन " होगा ।

एक स्टैंडअलोन को एक प्रतिकृति सेट में कैसे बदलें: https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set/


निम्नलिखित उदाहरण इस बात के लिए व्यावहारिक अनुप्रयोग है कि आप इसका उपयोग कैसे कर सकते हैं।
* विशेष रूप से नोड के लिए।

/* file.js */
'use strict'


module.exports = function (
    app,
    io,
    User // Collection Name
) {
    // SET WATCH ON COLLECTION 
    const changeStream = User.watch();  

    // Socket Connection  
    io.on('connection', function (socket) {
        console.log('Connection!');

        // USERS - Change
        changeStream.on('change', function(change) {
            console.log('COLLECTION CHANGED');

            User.find({}, (err, data) => {
                if (err) throw err;

                if (data) {
                    // RESEND ALL USERS
                    socket.emit('users', data);
                }
            });
        });
    });
};
/* END - file.js */

उपयोगी लिंक्स:
https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set
https://docs.mongodb.com/manual/tutorial/change-streams-example

https://docs.mongodb.com/v3.6/tutorial/change-streams-example
http://plusnconsulting.com/post/MongoDB-Change-Streams


सभी संपादन के बारे में क्षमा करें, SO को मेरा "लिंक" पसंद नहीं आया (कहा कि वे अनुचित रूप से कोडित कोड थे।)
रियो वेबर

1
आपको डेटाबेस को क्वेरी नहीं करना चाहिए, मुझे लगता है कि वॉच () या इसी तरह का नया डेटा सर्वर पर भेजा जा सकता है जो सुन रहा है
अलेक्जेंडर मिल्स

22

MongoDB संस्करण 3.6 में अब परिवर्तन धाराएं शामिल हैं जो अनिवार्य रूप से ट्रिगर / अधिसूचना जैसे उपयोग मामलों के लिए अनुमति देने वाले OpLog के ऊपर एक एपीआई है।

यहाँ जावा उदाहरण के लिए एक लिंक दिया गया है: http://mongodb.github.io/mongo-java-driver/3.6/driver/tutorials/change-streams/

NodeJS उदाहरण कुछ इस तरह दिख सकता है:

 var MongoClient = require('mongodb').MongoClient;
    MongoClient.connect("mongodb://localhost:22000/MyStore?readConcern=majority")
     .then(function(client){
       let db = client.db('MyStore')

       let change_streams = db.collection('products').watch()
          change_streams.on('change', function(change){
            console.log(JSON.stringify(change));
          });
      });

JSON.stringify Android Studio (Android App) में यह डेटा प्राप्त करना बहुत महत्वपूर्ण है ..
DragonFire

3

वैकल्पिक रूप से, आप मानक Mongo FindAndUpdate पद्धति का उपयोग कर सकते हैं, और कॉलबैक के भीतर, कॉलबैक चलाने पर एक EventEmitter घटना (नोड में) को आग लगा सकते हैं।

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


यह बहुत ही अक्षम है..आप प्रत्येक FindAndUpdate के लिए db को लॉक कर रहे हैं!
यश गुप्ता

1
मेरा अनुमान है कि एलेक्स थोड़ा अलग जवाब दे रहा था (विशेष रूप से आवेषण को संबोधित नहीं कर रहा था) लेकिन संबंधित प्रश्न कि ग्राहकों को किसी प्रकार की अधिसूचना को कैसे बंद किया जाए जब एक पंक्तिबद्ध नौकरी की स्थिति बदल जाती है जिसे हम मानते हैं कि नौकरियों के पैदा होने की आवश्यकता होगी। , पूर्ण रूप से सफलतापूर्वक या विफल। वेबस्केट्स को नोड से जोड़ने से जुड़े क्लाइंट के साथ, उन सभी को FIndAndUpdate कॉलबैक पर प्रसारण कार्यक्रम के साथ बदलावों के बारे में सूचित किया जा सकता है, जिन्हें राज्य परिवर्तन संदेश प्राप्त होने पर कॉल किया जा सकता है। मैं कहूंगा कि यह अक्षम नहीं है क्योंकि अपडेट किए जाने की आवश्यकता है।
पीटर स्कॉट

3

इनमें से कई जवाब आपको केवल नए रिकॉर्ड देंगे और अपडेट नहीं और / या बेहद अप्रभावी हैं

ऐसा करने का एकमात्र विश्वसनीय, निष्पादन योग्य तरीका यह है कि स्थानीय db: oplog.rs संग्रह पर MongoDB में सभी परिवर्तन प्राप्त करने के लिए एक संग्रहणीय कर्सर बनाया जाए और इसके साथ आप क्या करेंगे। (MongoDB भी प्रतिकृति का समर्थन करने के लिए आंतरिक रूप से कम या ज्यादा करता है!)

ओप्लॉग में क्या शामिल है की व्याख्या: https://www.compose.com/articles/the-mongodb-oplog-and-node-js/

Node.js लाइब्रेरी का उदाहरण जो अफीम के साथ उपलब्ध होने के लिए एक एपीआई प्रदान करता है: https://github.com/cayasso/mongo-oplog


2

MongoDB Stitch नामक सेवाओं का एक भयानक सेट उपलब्ध है । में देखो सिलाई कार्य / चलाता । ध्यान दें कि यह क्लाउड-आधारित भुगतान सेवा (AWS) है। आपके मामले में, सम्मिलित करने पर, आप जावास्क्रिप्ट में लिखे गए कस्टम फ़ंक्शन को कॉल कर सकते हैं।

यहां छवि विवरण दर्ज करें


stackoverflow.com/users/486867/manish-jain - क्या आपके पास एक उदाहरण है कि कैसे एक REACT एप्लिकेशन को सूचित करने के लिए सिलाई का उपयोग किया जा सकता है कि डेटा एक तालिका में डाला गया था?
MLissCetrus 20

1

एक काम जावा उदाहरण है जो यहां पाया जा सकता है

 MongoClient mongoClient = new MongoClient();
    DBCollection coll = mongoClient.getDatabase("local").getCollection("oplog.rs");

    DBCursor cur = coll.find().sort(BasicDBObjectBuilder.start("$natural", 1).get())
            .addOption(Bytes.QUERYOPTION_TAILABLE | Bytes.QUERYOPTION_AWAITDATA);

    System.out.println("== open cursor ==");

    Runnable task = () -> {
        System.out.println("\tWaiting for events");
        while (cur.hasNext()) {
            DBObject obj = cur.next();
            System.out.println( obj );

        }
    };
    new Thread(task).start();

कुंजी यहाँ दिए गए QUERY विकल्प है।

इसके अलावा, आप क्वेरी को बदल सकते हैं, यदि आपको हर बार सभी डेटा लोड करने की आवश्यकता नहीं है।

BasicDBObject query= new BasicDBObject();
query.put("ts", new BasicDBObject("$gt", new BsonTimestamp(1471952088, 1))); //timestamp is within some range
query.put("op", "i"); //Only insert operation

DBCursor cur = coll.find(query).sort(BasicDBObjectBuilder.start("$natural", 1).get())
.addOption(Bytes.QUERYOPTION_TAILABLE | Bytes.QUERYOPTION_AWAITDATA);

1

वास्तव में, आउटपुट देखने के बजाय, आपको सूचना क्यों नहीं मिलती है जब कुछ नया मध्य-बर्तन का उपयोग करके डाला जाता है जो कि मैंगोज़ोज़ स्कीमा द्वारा प्रदान किया गया था

आप एक नया दस्तावेज़ सम्मिलित करने की घटना को पकड़ सकते हैं और इस प्रविष्टि के बाद कुछ कर सकते हैं


मेरी गलती। क्षमा करें श्रीमान।
डुओंग गुयेन

0

3.6 के बाद डेटाबेस का उपयोग करने की अनुमति है निम्नलिखित डेटाबेस ट्रिगर प्रकार:

  • ईवेंट-चालित ट्रिगर्स - संबंधित दस्तावेज़ों को स्वचालित रूप से अपडेट करने, डाउनस्ट्रीम सेवाओं को सूचित करने, मिश्रित वर्कलोड का समर्थन करने के लिए डेटा का प्रसार करने, डेटा अखंडता और ऑडिटिंग के लिए उपयोगी।
  • अनुसूचित ट्रिगर - अनुसूचित डेटा पुनर्प्राप्ति, प्रसार, अभिलेखीय और विश्लेषण कार्यभार के लिए उपयोगी

अपने एटलस खाते में प्रवेश करें Triggersऔर इंटरफ़ेस चुनें और नया ट्रिगर जोड़ें:

यहां छवि विवरण दर्ज करें

अधिक सेटिंग्स या विवरण के लिए प्रत्येक अनुभाग का विस्तार करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.