MongoDb में, आप इसके इंडेक्स द्वारा एरे तत्व को कैसे हटाते हैं?


97

निम्नलिखित उदाहरण में, मान लें कि दस्तावेज़ db.people संग्रह में है।

अनुक्रमणिका द्वारा रुचियों के 3 तत्व को कैसे हटाया जाए ?

{
  "_id" : ObjectId("4d1cb5de451600000000497a"),           
  "name" : "dannie",  
  "interests" : [  
    "guitar",  
    "programming",           
    "gadgets",  
    "reading"  
  ]   
}

यह मेरा वर्तमान समाधान है:

var interests = db.people.findOne({"name":"dannie"}).interests;  
interests.splice(2,1)  
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});

क्या कोई और सीधा रास्ता है?


जवाबों:


138

सरणी सूचकांक द्वारा खींचने / हटाने का कोई सीधा तरीका नहीं है। वास्तव में, यह एक खुला मुद्दा है http://jira.mongodb.org/browse/SERVER-1014 , आप इसके लिए वोट कर सकते हैं।

समाधान $ unset और फिर $ पुल का उपयोग कर रहा है:

db.lists.update({}, {$unset : {"interests.3" : 1 }}) 
db.lists.update({}, {$pull : {"interests" : null}})

अपडेट: जैसा कि कुछ टिप्पणियों में उल्लेख किया गया है, यह दृष्टिकोण परमाणु नहीं है और कुछ दौड़ की स्थिति पैदा कर सकता है यदि अन्य क्लाइंट दो ऑपरेशनों के बीच पढ़ते हैं और / या लिखते हैं। यदि हमें परमाणु होने के लिए ऑपरेशन की आवश्यकता है, तो हम कर सकते हैं:

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

33
डेढ़ साल हो गया? क्या यह अभी भी मोंगोडब वाली चीजों की स्थिति है?
अबे

अगला उत्तर अधिक प्रत्यक्ष और मेरे लिए काम किया है। हालांकि यह इंडेक्स द्वारा नहीं निकाला जा रहा है, बल्कि वैल्यू से हटा रहा है।
विंश

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

यह परमाणु नहीं है, इसलिए यह अस्पष्ट दौड़ की स्थिति पैदा करने की संभावना है यदि आपके पास कोई कोड है जो सरणी में एक अशक्त प्रविष्टि के साथ सामना करने के लिए तैयार नहीं है।
ग्लेन मेनार्ड

3
8 साल और यह टिकट अभी भी लागू नहीं किया गया है ...
ओली जॉन

19

आप किसी सरणी में किसी विशेष तत्व को हटाने के लिए ऑपरेशन के $pullसंशोधक का उपयोग कर सकते हैं update। यदि आपने कोई क्वेरी दी है तो ऐसा दिखेगा:

db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}})

इसके अलावा, आप $pullAllसभी घटनाओं को हटाने के लिए उपयोग करने पर विचार कर सकते हैं । इसके बारे में आधिकारिक दस्तावेज पृष्ठ पर अधिक जानकारी - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull

यह तत्व को हटाने के लिए एक मापदंड के रूप में सूचकांक का उपयोग नहीं करता है, लेकिन फिर भी आपके जैसे मामलों में मदद कर सकता है। IMO, किसी सरणी के अंदर तत्वों को संबोधित करने के लिए अनुक्रमित का उपयोग करना बहुत विश्वसनीय नहीं है क्योंकि mongodb एक तत्व क्रम पर संगत नहीं है जैसा कि मुझे पता है।


6
उसका तत्व प्रश्न में एक सरणी है। मोंगो इस मामले में आदेश पर संगत है। वास्तव में, सभी दस्तावेजों को वास्तव में संग्रह का आदेश दिया जाता है, लेकिन कई ड्राइवर इस तरह से उन्हें संभाल नहीं पाते हैं। इस मामले को और उलझाते हुए, अगर किसी दस्तावेज़ को अपडेट ऑपरेशन (पेडिंग फैक्टर से आगे बढ़ने के कारण) के बाद स्थानांतरित किया जाना है, तो चाबी का क्रम अचानक वर्णानुक्रमिक हो जाता है (कवर के तहत, मुझे लगता है कि वे अपने द्विआधारी मूल्य द्वारा क्रमबद्ध हैं, यह संदेह है मेरे ज्ञान के आधार पर कि सरणियाँ कुंजियों के साथ बहुत मानक दस्तावेज़ हैं जो तार के बजाय लगातार पूर्णांक हैं)।
marr75

यह परेशान + खींच की समस्याओं से बचा जाता है, लेकिन इसके लिए आवश्यक है कि आपके शब्दकोश को सख्ती से क्रमबद्ध किया जाए। अधिकांश भाषाओं के शब्दकोश अनियंत्रित हैं, इसलिए ऐसा होने के लिए दर्द हो सकता है।
ग्लेन मेनार्ड

@ marr75: क्या आपके पास एक संदर्भ है? मानगो दस्तावेजों को हमेशा आदेश को बनाए रखने के लिए माना जाता है, और अगर यह कभी भी तोड़-फोड़ करता है तो बहुत सी चीजें टूट जाएंगी।
ग्लेन मेनार्ड

मेरे पास कोई संदर्भ नहीं है। मैं 2.2 के साथ व्यक्तिगत अनुभव से यह जानता हूं, फिक्स्ड बग्स हैं जो अद्यतन और स्थानांतरित दस्तावेजों द्वारा पेश किए गए थे। मैंने पिछले कुछ महीनों में बहुत अधिक काम नहीं किया है इसलिए मैं अधिक वर्तमान संस्करणों के लिए बात नहीं कर सकता।
marr75

जहां तक ​​तत्व स्थिरता की बात है, मेरा वांछित उपयोग मामला है। एक ग्राहक मोंगो से json का अनुरोध करता है और फिर अगर ग्राहक किसी आइटम को json सरणी से 'डिलीट' करने का विकल्प चुनता है, तो वह सरणी इंडेक्स को सर्वर से डिलीट कर देगा। अगर सरणी आइटम की स्थिति चली गई, तो यह अजीब होगा, लेकिन यह
बताएगा

4

अनसेट (स्वीकृत उत्तर के अनुसार) का उपयोग करने के बजाय, मैं फ़ील्ड को एक अद्वितीय मान (यानी NULL नहीं) पर सेट करके और फिर तुरंत उस मान को खींचकर हल करता हूं। एक आश्रय के दृष्टिकोण से थोड़ा सुरक्षित। यहाँ कोड है:

    var update = {};
    var key = "ToBePulled_"+ new Date().toString();
    update['feedback.'+index] = key;
    Venues.update(venueId, {$set: update});
    return Venues.update(venueId, {$pull: {feedback: key}});

उम्मीद है कि मोंगो इसे संबोधित करेंगे, शायद $ पुल और साथ ही $ पुश का समर्थन करने के लिए $ स्थिति संशोधक का विस्तार करें।


3

मैं सरणी में प्रत्येक उप-दस्तावेज़ के लिए एक GUID (मैं ऑब्जेक्ट का उपयोग करने के लिए) फ़ील्ड या एक ऑटो-इंक्रीमेंटिंग फ़ील्ड का उपयोग करने की सलाह दूंगा।

इस GUID के साथ $ खींच जारी करना आसान है और सुनिश्चित करें कि सही एक खींच लिया जाएगा। वही अन्य सरणी संचालन के लिए जाता है।


2

में शुरू Mongo 4.4, $functionएकत्रीकरण ऑपरेटर MongoDB क्वेरी भाषा द्वारा समर्थित व्यवहार को लागू करने के लिए एक कस्टम जावास्क्रिप्ट फ़ंक्शन को लागू करने की अनुमति देता है।

उदाहरण के लिए, किसी दिए गए सूचकांक में एक तत्व को हटाकर एक सरणी को अद्यतन करने के लिए:

// { "name": "dannie", "interests": ["guitar", "programming", "gadgets", "reading"] }
db.collection.update(
  { "name": "dannie" },
  [{ $set:
    { "interests":
      { $function: {
          body: function(interests) { interests.splice(2, 1); return interests; },
          args: ["$interests"],
          lang: "js"
      }}
    }
  }]
)
// { "name": "dannie", "interests": ["guitar", "programming", "reading"] }

$function 3 पैरामीटर लेता है:

  • body, जो लागू करने के लिए फ़ंक्शन है, जिसका पैरामीटर संशोधित करने के लिए सरणी है। इंडेक्स 2 में 1 तत्व को हटाने के लिए फंक्शन का उपयोग केवल ब्याह में होता है।
  • args, जिसमें रिकॉर्ड से फ़ील्ड्स होते हैं जो bodyफ़ंक्शन पैरामीटर के रूप में लेता है। हमारे मामले में "$interests"
  • lang, जो वह भाषा है जिसमें bodyफ़ंक्शन लिखा जाता है। केवल jsवर्तमान में उपलब्ध है।

2

मोंगोडब 4.2 में आप ऐसा कर सकते हैं:

db.example.update({}, [
     {$set: {field: {
           $concatArrays: [ 
                  {$slice: ["$field", P]}, 
                  {$slice: ["$field", {$add: [1, P]}, {$size: "$field"}]}
           ]
     }}}
]);

P उस तत्व का सूचकांक है जिसे आप सरणी से हटाना चाहते हैं।

यदि आप P को अंत तक हटाना चाहते हैं:

db.example.update({}, [
     {$set: {field: {$slice: ["$field", P]}}
]);

0

उन लोगों के लिए जो नोडज के साथ आम का उपयोग करके उत्तर खोज रहे हैं। यह मेरा इसे करने का तरीका है।

exports.deletePregunta = function (req, res) {
let codTest = req.params.tCodigo;
let indexPregunta = req.body.pregunta; // the index that come from frontend
let inPregunta = `tPreguntas.0.pregunta.${indexPregunta}`; // my field in my db
let inOpciones = `tPreguntas.0.opciones.${indexPregunta}`; // my other field in my db
let inTipo = `tPreguntas.0.tipo.${indexPregunta}`; // my  other field in my db

Test.findOneAndUpdate({ tCodigo: codTest },
    {
        '$unset': {
            [inPregunta]: 1, // put the field with [] 
            [inOpciones]: 1,
            [inTipo]: 1
        }
    }).then(()=>{ 
    Test.findOneAndUpdate({ tCodigo: codTest }, {
        '$pull': {
            'tPreguntas.0.pregunta': null,
            'tPreguntas.0.opciones': null,
            'tPreguntas.0.tipo': null
        }
    }).then(testModificado => {
        if (!testModificado) {
            res.status(404).send({ accion: 'deletePregunta', message: 'No se ha podido borrar esa pregunta ' });
        } else {
            res.status(200).send({ accion: 'deletePregunta', message: 'Pregunta borrada correctamente' });
        }
    })}).catch(err => { res.status(500).send({ accion: 'deletePregunta', message: 'error en la base de datos ' + err }); });
 }

अगर यह बहुत अच्छी तरह से समझ में नहीं आता है, तो मैं इस जवाब को फिर से लिख सकता हूं, लेकिन मुझे लगता है कि यह ठीक है।

आशा है कि यह आपकी मदद करेगा, मैंने इस मुद्दे का सामना करने में बहुत समय खो दिया।


-3

$ पुल का उपयोग करने के बजाय हम इसके सूचकांक द्वारा किसी सरणी में तत्वों को निकालने के लिए $ पॉप का उपयोग कर सकते हैं। लेकिन आपको सूचकांक के आधार पर हटाने के लिए सूचकांक स्थिति से 1 घटा देना चाहिए।

उदाहरण के लिए यदि आप इंडेक्स 0 में तत्व को हटाना चाहते हैं, तो आपको -1 का उपयोग करना चाहिए, इंडेक्स 1 के लिए आपको 0 और इसी तरह का उपयोग करना चाहिए ...

तृतीय तत्व निकालने के लिए क्वेरी (गैजेट):

db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})

संदर्भ के लिए: https://docs.mongodb.com/manual/reference/operator/update/pop/


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