2015-03-16 4 views
11

मैं एक संग्रह बनाया और इसMongoDB डुप्लीकेट दस्तावेज भी जोड़ने के बाद अद्वितीय कुंजी

db.user_services.createIndex({"uid":1 , "sid": 1},{unique:true,dropDups: true}) 

की तरह एक अद्वितीय कुंजी जोड़ा संग्रह इस "user_services"

{ 
"_id" : ObjectId("55068b35f791c7f81000002d"), 
"uid" : 15, 
"sid" : 1, 
"rate" : 5 
}, 
{ 

"_id" : ObjectId("55068b35f791c7f81000002f"), 
"uid" : 15, 
"sid" : 1, 
"rate" : 4 
} 

समस्या तरह दिखता है:

उसी uid और s के साथ दस्तावेज़ डालने के लिए php ड्राइवर का उपयोग कर रहा हूँ आईडी और यह डाला जा रहा है।

मैं क्या चाहता हूँ

  1. मोंगो शैल पर: uid और सिड पर अद्वितीय कुंजी एक ही uid और सिड के साथ कोई डुप्लिकेट दस्तावेजों के साथ जोड़ें।
  2. PHP साइड पर: mysql जैसे कुछ "डुप्लिकेट कुंजी अपडेट दर = दर + 1" पर डालें (मान)। यही कारण है कि जब भी मैं एक दस्तावेज़ को सम्मिलित करने का प्रयास करें, यह यदि ऐसा नहीं यह दस्तावेज़ के दर क्षेत्र अद्यतन करना चाहिए

उत्तर

28

बधाई डाला जाना चाहिए है, तो आप एक बग पाया है दिखाई देते हैं। यह केवल मेरे परीक्षण में MongoDB 3.0.0 के साथ होता है, या कम से कम MongoDB 2.6.6 पर मौजूद नहीं है। बग अब कम से SERVER-17599

नोट दर्ज की गई: नहीं वास्तव में एक "विषय" लेकिन "डिजाइन द्वारा" की पुष्टि की। संस्करण 3.0.0 के लिए विकल्प छोड़ दिया। फिर भी documentation में सूचीबद्ध है।

समस्या यह है कि जब आप "कंपाउंड कुंजी" फ़ील्ड पर मौजूदा डुप्लिकेट वाले संग्रह पर इसे बनाने का प्रयास करते हैं तो समस्या उत्पन्न नहीं होती है और त्रुटियां होती हैं। इसके बाद के संस्करण पर, सूचकांक निर्माण खोल में इस उपज चाहिए:

{ 
    "createdCollectionAutomatically" : false, 
    "numIndexesBefore" : 1, 
    "errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }", 
    "code" : 11000, 
    "ok" : 0 
} 

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

तो इस को हल करने के लिए, पहले इस तरह की एक प्रक्रिया के साथ डुप्लिकेट निकालने:

db.events.aggregate([ 
    { "$group": { 
     "_id": { "uid": "$uid", "sid": "$sid" }, 
     "dups": { "$push": "$_id" }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$match": { "count": { "$gt": 1 } }} 
]).forEach(function(doc) { 
    doc.dups.shift(); 
    db.events.remove({ "_id": {"$in": doc.dups }}); 
}); 

db.events.createIndex({"uid":1 , "sid": 1},{unique:true}) 

फिर आगे डुप्लिकेट डेटा युक्त आवेषण शामिल नहीं किया जाएगा और उचित त्रुटि दर्ज किया जाएगा।

अंतिम नोट यह है कि "ड्रॉपडप्स" डुप्लिकेट डेटा को हटाने के लिए एक बहुत ही सुरुचिपूर्ण समाधान नहीं है। जैसा कि ऊपर दिखाया गया है, आप वास्तव में कुछ नियंत्रण के साथ कुछ चाहते हैं।

.insert() का उपयोग करने के बजाय दूसरे भाग के लिए .update() विधि का उपयोग करें। यह एक "upsert" विकल्प

$collection->update(
    array("uid" => 1, "sid" => 1), 
    array('$set' => $someData), 
    array('upsert' => true) 
); 

तो "पाया" दस्तावेज़ "संशोधित" कर रहे हैं और दस्तावेज नहीं मिला "डाला" कर रहे हैं।जब दस्तावेज़ वास्तव में डाला जाता है और संशोधित नहीं किया जाता है तो केवल कुछ डेटा बनाने के लिए $setOnInsert देखें।


अपने विशिष्ट प्रयास के लिए, .update() की सही सिंटैक्स तीन तर्कों है। "क्वेरी", "अद्यतन" और "विकल्प":

$collection->update(
    array("uid" => 1, "sid" => 1), 
    array(
     '$set' => array("field" => "this"), 
     '$inc' => array("counter" => 1), 
     '$setOnInsert' => array("newField" => "another") 
    ), 
    array("upsert" => true) 
); 

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

+2

dropDups विकल्प ([MongoDB 3.0 में हटाया] था http://docs.mongodb.org: बस, इस क्वेरी चलाने yourDuplicateKey की जगह और _id माना आपके प्राथमिक कुंजी (सुनिश्चित करें कि आप सिर्फ मामले में mongodump बनाने) है /manual/release-notes/3.0-compatibility/#remove-dropdups-option)। यह भी देखें: [सेवर -14710] (https://jira.mongodb.org/browse/SERVER-14710)। डेटा का गैर-निर्धारिती विलोपन इंडेक्स विकल्प का एक अप्रत्याशित साइड इफेक्ट था। – Stennie

+0

@ स्टेनी। समझ में आता है। इस कारण के लिए इसे कभी भी इस्तेमाल नहीं किया। अभी भी [प्रलेखन] (http://docs.mongodb.org/manual/tutorial/create-a-unique-index/) में हालांकि समस्या का स्रोत होगा। –

+0

धन्यवाद, दस्तावेज़ों पर अच्छी पकड़! मैं इसके लिए [एक जिरा उठाऊंगा] (https://jira.mongodb.org/browse/DOCS) :) – Stennie

7

मुझे लगता है कि वर्तमान सबसे लोकप्रिय उत्तर थोड़ा स्थानीय है और इस तरह के एक प्राथमिक मोंगोडीबी ऑपरेशन के लिए विस्तृत है - एक कुंजी द्वारा मोंगो से डुप्लिकेट को हटा रहा है।

मोंगो> 3.0 के लिए एक कुंजी द्वारा डुप्लीकेट हटाने को सरल है।

db.yourCollection.aggregate([ 
    { "$group": { 
     "_id": { "yourDuplicateKey": "$yourDuplicateKey" }, 
     "dups": { "$push": "$_id" }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$match": { "count": { "$gt": 1 } }} 
]).forEach(function(doc) { 
    doc.dups.shift(); 
    db.yourCollection.remove({ "_id": {"$in": doc.dups }}); 
}); 
संबंधित मुद्दे