mongoDB / mongoose: अद्वितीय यदि शून्य नहीं है


103

मैं सोच रहा था कि क्या कोई अनूठा संग्रह प्रविष्टि को मजबूर करने का तरीका है, लेकिन केवल अगर प्रविष्टि शून्य नहीं है । ई नमूना स्कीमा:

var UsersSchema = new Schema({
    name  : {type: String, trim: true, index: true, required: true},
    email : {type: String, trim: true, index: true, unique: true}
});

इस मामले में 'ईमेल' की आवश्यकता नहीं है, लेकिन अगर 'ईमेल' बच गया है, तो मैं यह सुनिश्चित करना चाहता हूं कि यह प्रविष्टि अद्वितीय है (डेटाबेस स्तर पर)।

रिक्त प्रविष्टियों का मान 'शून्य' प्राप्त होता है, इसलिए प्रत्येक प्रविष्टि wih कोई ईमेल 'अद्वितीय' विकल्प के साथ क्रैश नहीं होती है (यदि कोई ईमेल वाला कोई भिन्न उपयोगकर्ता है)।

अभी मैं इसे एक एप्लिकेशन स्तर पर हल कर रहा हूं, लेकिन उस db क्वेरी को सहेजना अच्छा लगेगा।

धन्यवाद

जवाबों:


169

MongoDB v1.8 + के रूप में आप अनूठे मूल्यों को सुनिश्चित करने का वांछित व्यवहार प्राप्त कर सकते हैं, लेकिन sparseसूचकांक को परिभाषित करते समय विकल्प को सही पर सेट करके क्षेत्र के बिना कई डॉक्स की अनुमति दे सकते हैं । जैसे की:

email : {type: String, trim: true, index: true, unique: true, sparse: true}

या शेल में:

db.users.ensureIndex({email: 1}, {unique: true, sparse: true});

ध्यान दें कि एक अद्वितीय, विरल सूचकांक अभी भी एक साथ कई डॉक्स की अनुमति नहीं है emailएक साथ मैदान मूल्य की null, केवल कई डॉक्स के बिना एक emailक्षेत्र।

Http://docs.mongodb.org/manual/core/index-sparse/ देखें


18
बहुत बढ़िया! निश्चित रूप से 1.8 के बाद मेरे जैसे नए लोगों के लिए सबसे अच्छा जवाब! नोट: यदि आप सिर्फ एक स्पार्स जोड़ते हैं तो Mongoose आपके अद्वितीय सूचकांक को अपडेट नहीं करेगा: आपके स्कीमा के लिए सही। आपको इंडेक्स को छोड़ना और फिर से जोड़ना होगा। अगर यह अपेक्षित है या बग नहीं है।
एडम ए

8
"नोट: यदि सूचकांक पहले से ही db पर मौजूद है, तो इसे प्रतिस्थापित नहीं किया जाएगा।" - mongoosejs.com/docs/2.7.x/docs/schematypes.html
damphat

मुझे नहीं लगता कि यह सही ढंग से सवाल का जवाब देता है, क्योंकि एक विशिष्ट क्षेत्र के बिना कुछ दस्तावेज़ उस क्षेत्र पर एक शून्य मान के साथ कुछ दस्तावेज़ों के समान नहीं हैं (जो विशिष्ट रूप से अनुक्रमित नहीं किए जा सकते हैं)।
काको-नवाओ

1
@ kako-nawao यह सच है, यह केवल emailक्षेत्र के बिना डॉक्स के लिए काम करता है , न कि जहां वास्तव में इसका मूल्य है null। अद्यतन उत्तर देखें।
जॉनीएचके

2
लापता फ़ील्ड के साथ काम नहीं करता है। हो सकता है कि मोंगोडब के बाद के संस्करणों में व्यवहार को बदल दिया गया था। उत्तर को अद्यतन किया जाना चाहिए।
जोंबा 16

44

tl; डॉ

हां, nullअद्वितीय "वास्तविक" मानों को लागू करते हुए, एक फ़ील्ड सेट के साथ कई दस्तावेज़ों को परिभाषित या परिभाषित नहीं किया जाना संभव है ।

आवश्यकताएँ :

  • MongoDB v3.2 +।
  • अपने ठोस मूल्य प्रकारों को पहले से जानना (जैसे, हमेशा stringया objectजब नहीं null)।

यदि आप विवरणों में रुचि नहीं रखते हैं, तो implementationअनुभाग पर जाने के लिए स्वतंत्र महसूस करें ।

लंबा संस्करण

MongoDB v3.2 से शुरू होने वाले @ नोलन के उत्तर को पूरक करने के लिए, आप फ़िल्टर अभिव्यक्ति के साथ एक आंशिक अद्वितीय सूचकांक का उपयोग कर सकते हैं।

आंशिक फ़िल्टर अभिव्यक्ति की सीमाएँ हैं। इसमें केवल निम्नलिखित शामिल हो सकते हैं:

  • समानता के भाव (अर्थात क्षेत्र: मूल्य या $eqऑपरेटर का उपयोग करके ),
  • $exists: true अभिव्यक्ति,
  • $gt, $gte, $lt, $lteभाव,
  • $type भाव,
  • $and केवल शीर्ष स्तर पर ऑपरेटर

इसका मतलब है कि तुच्छ अभिव्यक्ति का {"yourField"{$ne: null}}उपयोग नहीं किया जा सकता है।

हालांकि, यह मानते हुए कि आपका क्षेत्र हमेशा एक ही प्रकार का उपयोग करता है , आप एक $typeअभिव्यक्ति का उपयोग कर सकते हैं ।

{ field: { $type: <BSON type number> | <String alias> } }

MongoDB v3.6 ने कई संभावित प्रकारों को निर्दिष्ट करने के लिए समर्थन जोड़ा, जिसे एक सरणी के रूप में पारित किया जा सकता है:

{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }

जिसका अर्थ है कि यह मूल्य कई प्रकारों में से किसी एक के होने की अनुमति देता है जब नहीं null

इसलिए, यदि हम emailनीचे दिए गए उदाहरण में फ़ील्ड को या तो स्वीकार करने की अनुमति देना चाहते हैं stringया कहें, binary dataमान, एक उपयुक्त $typeअभिव्यक्ति होगी:

{email: {$type: ["string", "binData"]}}

कार्यान्वयन

नेवला

आप इसे एक मानसून स्कीमा में निर्दिष्ट कर सकते हैं:

const UsersSchema = new Schema({
  name: {type: String, trim: true, index: true, required: true},
  email: {
    type: String, trim: true, index: {
      unique: true,
      partialFilterExpression: {email: {$type: "string"}}
    }
  }
});

या सीधे इसे संग्रह में जोड़ें (जो मूल नोड का उपयोग करता है। जेएस चालक):

User.collection.createIndex("email", {
  unique: true,
  partialFilterExpression: {
    "email": {
      $type: "string"
    }
  }
});

देशी मोंगोडब ड्राइवर

का उपयोग करते हुए collection.createIndex

db.collection('users').createIndex({
    "email": 1
  }, {
    unique: true,
    partialFilterExpression: {
      "email": {
        $type: "string"
      }
    }
  },
  function (err, results) {
    // ...
  }
);

गेंदा का गोला

का उपयोग कर db.collection.createIndex:

db.users.createIndex({
  "email": 1
}, {
  unique: true, 
  partialFilterExpression: {
    "email": {$type: "string"}
  }
})

यह एक nullईमेल के साथ , या एक ईमेल क्षेत्र के बिना कई रिकॉर्ड डालने की अनुमति देगा , लेकिन एक ही ईमेल स्ट्रिंग के साथ नहीं।


बहुत बढ़िया जवाब। तुम एक रक्षक हो।
r3wt

यह जवाब मेरे लिए भी था।
इमैनुएल एनके

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

इस एक के लिए वोट किया गया है, क्योंकि यह ज्ञान प्रदान करता है और सबसे आम परिदृश्यों के आधार पर संभावित उत्तर पहले स्थान पर इस एसओ उत्तर पर समाप्त होगा। विस्तृत उत्तर के लिए धन्यवाद! : +1:
कोडरोड

6

इस विषय पर शोध करने वालों के लिए बस एक त्वरित अद्यतन।

चयनित उत्तर काम करेगा, लेकिन आप इसके बजाय आंशिक अनुक्रमित का उपयोग करने पर विचार कर सकते हैं।

संस्करण 3.2 में परिवर्तित: MongoDB 3.2 में शुरू, MongoDB आंशिक अनुक्रमित बनाने का विकल्प प्रदान करता है। आंशिक सूचकांक विरल अनुक्रमित की कार्यक्षमता का एक सुपरसेट प्रदान करते हैं। यदि आप MongoDB 3.2 या बाद के संस्करण का उपयोग कर रहे हैं, तो आंशिक सूचकांक को विरल इंडेक्स पर वरीयता दी जानी चाहिए।

आंशिक अनुक्रमित पर अधिक डोकोमो: https://docs.mongodb.com/manual/core/index-partial/


2

वास्तव में, केवल पहला दस्तावेज़ जहाँ फ़ील्ड के रूप में "ईमेल" मौजूद नहीं है, उसे सफलतापूर्वक सहेजा जाएगा। बाद में बचाता है जहां "ईमेल" मौजूद नहीं है, त्रुटि देते समय विफल हो जाएगा (नीचे कोड स्निपेट देखें)। कारण के लिए MongoDB आधिकारिक दस्तावेजों को यहां अद्वितीय सूचकांक और गुम कुंजी के संबंध में http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes पर देखें

  // NOTE: Code to executed in mongo console.

  db.things.ensureIndex({firstname: 1}, {unique: true});
  db.things.save({lastname: "Smith"});

  // Next operation will fail because of the unique index on firstname.
  db.things.save({lastname: "Jones"});

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

आप इसे http://www.mongodb.org/display/DOCS/Querying+and+nulls भी पढ़ना पसंद कर सकते हैं

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