2013-01-22 19 views
8

मेरे ऐप में कई उपयोगकर्ता हैं, प्रत्येक उपयोगकर्ता के पास दस्तावेज़ हैं। प्रत्येक दस्तावेज़ में अनुक्रम संख्या होना आवश्यक है, जो इस तरह कुछ दिख सकता है: 2013-1, 2013-2 (वर्ष और अनुक्रम संख्या), या शायद केवल एक साधारण संख्या: 1, 2, 3 ...मोंगो/मोंगोस में ऑटो वृद्धि दस्तावेज़ संख्या

वर्तमान में , जब मैं Mongoose docuemnt बनाया गया है, तो मैं उपयोगकर्ता की सेटिंग्स से अनुक्रम संख्या असाइन कर रहा हूं। उस अनुक्रम संख्या और उपयोगकर्ता की सेटिंग्स से संख्या प्रारूप के आधार पर, मैं अंतिम दस्तावेज़ संख्या उत्पन्न कर रहा हूं।

मुझे एहसास हुआ कि जब एक ही समय में 2 दस्तावेज़ बनाए जाते हैं, तो उन्हें बिल्कुल वही संख्या मिल जाएगी, क्योंकि मैं दस्तावेज़ सहेजने के बाद सेटिंग्स में अनुक्रम संख्या में वृद्धि कर रहा हूं। लेकिन मैं अनुक्रम संख्या असाइन कर रहा हूं जब मैं दस्तावेज़ बना रहा हूं (अभी तक सहेज नहीं रहा) तो अनुक्रम संख्या दोनों दस्तावेज़ों के लिए बिल्कुल वही होगी।

मैं स्पष्ट रूप से यह क्रम संख्या ऑटो बढ़ाने बचत के समय को संभालने के लिए कोई तरीका होना चाहिए ...

मैं कैसे आश्वस्त कर सकते हैं कि यह संख्या अद्वितीय है और स्वचालित रूप से वृद्धि की जाती/उत्पन्न?

+0

[डॉक्स] (hhttp: //www.wiredprairie.us/blog/index.php/archives/1524) दो अच्छे उदाहरण है। आप काउंटर उदाहरण का उपयोग कर सकते हैं और उपयोगकर्ता आईडी के लिए द्वितीयक कुंजी जोड़ सकते हैं, इसलिए यह प्रति उपयोगकर्ता अद्वितीय है। [MongoDB-autoincrement] (https://www.npmjs.com/package/mongodb-autoincrement) – WiredPrairie

+0

इस पुस्तकालय एक शॉट दे दो? साथ ही, मुझे यह सुनिश्चित करना होगा कि दस्तावेज़ उपयोगकर्ता एक उपयोगकर्ता के संदर्भ में अद्वितीय हैं। 2 उपयोगकर्ता हो सकते हैं, दोनों नंबर 1 के साथ केवल एक दस्तावेज़ हो सकते हैं। तो teh अद्वितीय अनुक्रमणिका को संख्या और उपयोगकर्ता _id पर विचार करना चाहिए। –

उत्तर

11

@emre और @WiredPraire ने मुझे सही दिशा में इंगित किया, लेकिन मैं अपने प्रश्न के लिए एक पूर्ण मोंगोस-संगत उत्तर प्रदान करना चाहता था। मैं निम्नलिखित समाधान के साथ समाप्त हो गया:

var Settings = new Schema({ 
    nextSeqNumber: { type: Number, default: 1 } 
}); 

var Document = new Schema({ 
    _userId: { type: Schema.Types.ObjectId, ref: "User" }, 
    number: { type: String } 
}); 

// Create a compound unique index over _userId and document number 
Document.index({ "_userId": 1, "number": 1 }, { unique: true }); 

// I make sure this is the last pre-save middleware (just in case) 
Document.pre('save', function(next) { 
    var doc = this; 
    // You have to know the settings_id, for me, I store it in memory: app.current.settings.id 
    Settings.findByIdAndUpdate(settings_id, { $inc: { nextSeqNumber: 1 } }, function (err, settings) { 
    if (err) next(err); 
    doc.number = settings.nextSeqNumber - 1; // substract 1 because I need the 'current' sequence number, not the next 
    next(); 
    }); 
}); 

कृपया ध्यान दें इस विधि के साथ वहाँ स्कीमा में नंबर पथ की आवश्यकता के लिए कोई रास्ता नहीं है कि, और कोई बिंदु के रूप में अच्छी तरह से है, क्योंकि यह स्वचालित रूप से जोड़ा जाता है।

+1

+1! क्यों यह काम करता है पर विस्तार से बता दें कि आप एक अवरुद्ध आपरेशन (एक लिखने, उदाहरण के लिए) की जरूरत है ताकि अतुल्यकालिक 'बचाने()' कॉल क्रम में पालन करें। "सरल" का उपयोग कर खोजें या संग्रह आप विफल रहता है पर बढ़ाने के लिए इच्छा गणना, क्योंकि दोनों का पता लगाएं और गणना कर रहे हैं गैर अवरुद्ध (आज्ञा पढ़ें) है, तो आप (संभावित) कई asynch साथ क्रमानुसार व्यवहार करने के लिए उन पर भरोसा नहीं किया जा सकता का समाधान 'सहेजें()' कॉल। –

+3

एक कोड नमूना पोस्ट करने के लिए धन्यवाद, इस समाधान मैं भी तलाश रहे हैं की तरह लग रहा है। यदि यह किसी के लिए उपयोगी है, तो मैंने इसे अनुकूलित भी किया ताकि आईडी केवल रचनाएं के लिए सहेजने पर कॉल हो और अद्यतन न हो: यदि (doc.isNew) {settings.findByIdAndUpdate ...} else {next(); } –

+0

क्या आप वाकई कुछ याद नहीं कर रहे हैं? मैं इस त्रुटि मिलती है "ऑब्जेक्ट # कोई तरीका है 'findByIdAndUpdate'" मुझे लगता है कि मैं पहली बार एक मॉडल बनाने के लिए है, नहीं किया है मैं? –

2

यह कोड MongoDB मैनुअल से लिया गया है और यह वास्तव में _id फ़ील्ड ऑटो वृद्धि करने का वर्णन करता है। हालांकि, इसे किसी भी क्षेत्र में लागू किया जा सकता है। आप जो चाहते हैं उसे जांचना है कि आपके दस्तावेज़ को डालने के बाद डेटाबेस में डाला गया मान मौजूद है या नहीं। यदि यह पहले से डाला गया है, तो मान को फिर से बढ़ाएं और फिर डालने का प्रयास करें। इस तरह आप गणराज्य मूल्यों का पता लगा सकते हैं और उन्हें फिर से बढ़ा सकते हैं।

while (1) { 

    var cursor = targetCollection.find({}, { f: 1 }).sort({ f: -1 }).limit(1); 

    var seq = cursor.hasNext() ? cursor.next().f + 1 : 1; 

    doc.f = seq; 

    targetCollection.insert(doc); 

    var err = db.getLastErrorObj(); 

    if(err && err.code) { 
     if(err.code == 11000 /* dup key */) 
      continue; 
     else 
      print("unexpected error inserting data: " + tojson(err)); 
    } 

    break; 
} 

इस उदाहरण में एफ आपके दस्तावेज़ में फ़ील्ड है जिसे आप ऑटो वृद्धि करना चाहते हैं। इस काम को करने के लिए आपको अपने क्षेत्र को अद्वितीय बनाने की आवश्यकता है जो इंडेक्स के साथ किया जा सकता है।

db.myCollection.ensureIndex({ "f": 1 }, { unique: true }) 
+1

हम्म, यह काम हो सकता है, लेकिन किसी भी विचार कैसे मैं नेवला साथ thsi लागू करना होगा: – ragulka

3

आपको लगता है कि के माध्यम से प्राप्त कर सकते हैं:

  1. अनुक्रम जनरेटर है, जो सिर्फ एक और दस्तावेज़ है कि पिछले संख्या का एक काउंटर रहता है पैदा करते हैं।
  2. इच्छित क्षेत्र में ऑटो वृद्धि को अपडेट करने के लिए मॉन्गोज़ मिडलवेयर का उपयोग करें।

यहां टोडो ऐप के साथ एक कामकाजी और परीक्षण किया गया उदाहरण है।

var mongoose = require('mongoose'); 
mongoose.connect('mongodb://localhost/todoApp'); 

// Create a sequence 
function sequenceGenerator(name){ 
    var SequenceSchema, Sequence; 

    SequenceSchema = new mongoose.Schema({ 
    nextSeqNumber: { type: Number, default: 1 } 
    }); 

    Sequence = mongoose.model(name + 'Seq', SequenceSchema); 

    return { 
    next: function(callback){ 
     Sequence.find(function(err, data){ 
     if(err){ throw(err); } 

     if(data.length < 1){ 
      // create if doesn't exist create and return first 
      Sequence.create({}, function(err, seq){ 
      if(err) { throw(err); } 
      callback(seq.nextSeqNumber); 
      }); 
     } else { 
      // update sequence and return next 
      Sequence.findByIdAndUpdate(data[0]._id, { $inc: { nextSeqNumber: 1 } }, function(err, seq){ 
      if(err) { throw(err); } 
      callback(seq.nextSeqNumber); 
      }); 
     } 
     }); 
    } 
    }; 
} 

// sequence instance 
var sequence = sequenceGenerator('todo'); 

var TodoSchema = new mongoose.Schema({ 
    name: String, 
    completed: Boolean, 
    priority: Number, 
    note: { type: String, default: '' }, 
    updated_at: { type: Date, default: Date.now } 
}); 

TodoSchema.pre('save', function(next){ 
    var doc = this; 
    // get the next sequence 
    sequence.next(function(nextSeq){ 
    doc.priority = nextSeq; 
    next(); 
    }); 
}); 

var Todo = mongoose.model('Todo', TodoSchema); 

आप के रूप में हर हाल में बनाई गई वस्तु आप प्राथमिकता में वृद्धि देखेंगे के साथ

function cb(err, data){ console.log(err, data); } 
Todo.create({name: 'hola'}, cb); 
Todo.find(cb); 

इस प्रकार यह पता नोड कंसोल में परीक्षण कर सकते हैं। चीयर्स!

2

आप इस प्रकार mongoose-auto-increment पैकेज का उपयोग कर सकते हैं:

var mongoose  = require('mongoose'); 
var autoIncrement = require('mongoose-auto-increment'); 

/* connect to your database here */ 

/* define your DocumentSchema here */ 

autoIncrement.initialize(mongoose.connection); 
DocumentSchema.plugin(autoIncrement.plugin, 'Document'); 
var Document = mongoose.model('Document', DocumentSchema); 

आप केवल एक बार autoIncrement प्रारंभ करने की जरूरत है।

+0

यदि आप https://stackoverflow.com/questions/45357813/issue-with-mongoose-auto-increment-plugin-in-nested-models में देख सकते हैं तो यह बहुत अच्छा होगा –