2010-06-28 5 views
5

मैं एक मोंगोडीबी नौसिखिया हूं और पूछना चाहता हूं कि अपरर्ट और सूची से जुड़े एक अद्यतन कमांड को कैसे लिखना है।मोंगो डीबी - सूचियों को शामिल करने वाले अप्सर्ट

{"_id" : ObjectId("4c28f62cbf8544c60506f11d"), 
"some_other_data":"goes here", 
"trips": [ 
    {"name": "2010-05-10", 
    "loc": [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
     {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}] 
    }, 
    {"name": "2010-05-08", 
    "loc": [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"}, 
     {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
     {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}] 
    } 
]} 

ध्यान दें कि:

असल में मैं कुछ इस तरह करना चाहते

  • आप एक यात्रा नाम और वर्तमान स्थान
  • आपूर्ति यात्रा पहले से ही मौजूद नहीं है, यह बनाने की आवश्यकता है
  • trips.name अद्वितीय होना चाहिए ताकि यदि यह exis हो ts, आप स्थान सरणी

यह क्वेरी है जिसे मैंने $ push के साथ स्थितित्मक ऑपरेटर को संयोजित किया था।

db.mycollection.update({"application_id": "MyTestApp", 
          "trips.name": "2010-05-10"}, 
          {$push: {'trips.$.loc': {"lat":11, "lng":11} }}, 
          true); 

लेकिन यह इस तरह डेटा में परिणाम:

> db.mycollection.find({"application_id":"MyTestApp"})   
{ "_id" : ObjectId("4c29044ebf8544c60506f11f"), 
"application_id" : "MyTestApp", 
"trips" : { "$" : { "loc" : [ { "lat" : 11, "lng" : 11 } ] }, 
"name" : "2010-05-10" } 
} 

आप देख सकते हैं कि

  • "यात्राएं" एक सरणी
  • ले लिया "$" सचमुच इसे नहीं बनाया है उस के साथ कुंजी (doh!)

अब तक मैं मोंगोडीबी के साथ बहुत खुश हूं, लेकिन जटिल प्रश्न लिखने के साथ निश्चित रूप से एक सीधी सीखने की वक्र है।

किसी भी प्रतिक्रिया की सराहना की जाएगी।

अग्रिम धन्यवाद, Amie

+0

फिर से नीचे मेरा उत्तर जाँच - मैं शामिल करने के लिए कि मैं क्या समाधान (या कम से कम कुछ है कि आप बहुत करीब मिलना चाहिए होने के लिए विश्वास है कि यह संपादित) – nearlymonolith

+0

यह [SO थ्रेड] देखें (http://stackoverflow.com/questions/17994552/mongodb-update- दस्तावेज़-in-an-array/17995495#17995495)। कुछ इसी तरह के समान है। – user10

उत्तर

4

आप कर सकते हैं स्थितित्मक ऑपरेटर ("$") और एक अपरिवर्तनीय मिश्रण नहीं है; डालने के दौरान "$" को फ़ील्ड नाम के रूप में माना जाएगा। आप इसे नए दस्तावेज़ों के लिए नहीं कर सकते हैं, केवल मौजूदा एक।

मैं एक संरचना इस तरह के और अधिक सुझाव: इस डाला जा रहा है में

db.mycollection.update({application_id: "MyTestApp", "trips.2010-05-10":{$exists:true}}, 
         {$push: {"trips.2010-05-10": {lat:11, lng:11} }}, 
         true); 

परिणाम:

{"_id" : ObjectId("4c28f62cbf8544c60506f11d"), 
"some_other_data":"goes here", 
"trips": { 
    "2010-05-10": 
     [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
     {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}], 
    "2010-05-08": 
     [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"}, 
     {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
     {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}] 
    } 
} 

तो फिर तुम इस तरह एक अद्यतन जारी कर सकते हैं।

> db.mycollection.find() 
{ "_id" : ObjectId("4c2931d17b210000000045f0"), 
    "application_id" : "MyTestApp", 
    "trips" : { "2010-05-10" : [ { "lat" : 11, "lng" : 11 } ] } } 

और इसे फिर से चल रहा है आप दे इस:

> db.mycollection.find() 
{ "_id" : ObjectId("4c2932db7b210000000045f2"), 
    "application_id" : "MyTestApp", 
    "trips" : { "2010-05-10" : 
     [ { "lat" : 11, "lng" : 11 }, 
      { "lat" : 11, "lng" : 11 } ] } } 
+0

यह मैंने जो हासिल करने की कोशिश की है उससे बहुत करीब है। धन्यवाद @ स्कॉट हर्नान्डेज़। इस स्कीमा के साथ, "ट्रिप" में कुंजियों की एक सूची पुनर्प्राप्त करना संभव है? ("2010-050-10", आदि) db.mycollection.find ({"application_id": "MytestApp"}, {"trips": true}) पूरे "ट्रिप" हैश देता है। – Grnbeagle

+0

मैं इस विधि के साथ जा रहा समाप्त हो गया। समाधान स्कॉट के लिए धन्यवाद! – Grnbeagle

+0

समस्या यह है कि आप यात्रा के भीतर कुछ के लिए पूछ नहीं सकते हैं, जैसे कि 21.321231 पर एक यात्रा के साथ दस्तावेज़ ढूंढें (जैसा कि मोंगो (आज) के पास मैदान के पथ के 'वाइल्ड-कार्ड' भाग का कोई तरीका नहीं है)। – Nick

1

सही समाधान

शामिल करने के लिए यह ठीक समस्या मैं मोंगो सीखने हिट है संपादित - आप $addToSet ऑपरेटर (see docs here) है कि के साथ प्रयोग किया की तलाश कर रहे update कमांड, $ स्थितित्मक ऑपरेटर के साथ संयोजन में आप उपयोग कर रहे थे।

$ addToSet

{$ addToSet: {क्षेत्र: मूल्य}} सरणी केवल अगर अपने सरणी में नहीं पहले से ही करने के लिए

जोड़ता मूल्य।

इस प्रकार क्वेरी (डीबी।ढेर संग्रह मैं परीक्षण प्रयोजनों के लिए प्रयोग किया जाता है) है, का पालन करें नमूना चलाने के लिए:

db.stack.update({ "trips.name":"2010-05-10" }, 
       { $addToSet: { "trips.$.loc":{"lat":11, "lng":12} } } 
       ); 

परीक्षण चलाने (कुछ संक्षिप्त रूपों के साथ तत्वों है कि महत्वपूर्ण नहीं हैं) के अंतरिक्ष के लिए:

#### YOUR ITEM IN THE DB 
> db.stack.find({"trips.name":"2010-05-10"}) 
{ "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here", 
    "trips" : [ 
    { "name" : "2010-05-10", 
     "loc" : [ { 
       "lat" : 21.321231, 
       "lng" : 16.8783234, 
       "updated_at" : "Mon May 10 2010 15:24:35" 
      }, { "lat" : 21.321231, 
       "lng" : 16.8783234, 
       "updated_at" : "Mon May 10 2010 15:24:24" 
      } ] }, 
    { "name" : "2010-05-08", 
     "loc" : [ ... ] 
    } ] } 
#### SUCCESSFULLY ADDS ITEM TO PROPER ARRAY 
> db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":11}}}); 
> db.stack.findOne() 
{ "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here", 
    "trips" : [ 
     { "loc" : [ 
       { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:35" 
       }, { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:24" 
       }, { "lat" : 11, 
        "lng" : 11 
       } 
      ], "name" : "2010-05-10" 
     }, 
     { "name" : "2010-05-08", 
      "loc" : [ ... ] 
     } ] } 
#### ON REPEAT RUN DOESN'T ADD NEW ELEMENT 
> db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":11}}}); 
> db.stack.findOne() 
{ "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here", 
    "trips" : [ { 
      "loc" : [ 
       { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:35" 
       }, { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:24" 
       }, { "lat" : 11, 
        "lng" : 11 
       } 
      ], "name" : "2010-05-10" 
     }, 
     { "name" : "2010-05-08", 
      "loc" : [ ... ] 
     } ] } 
#### BUT WILL CORRECTLY ADD ANOTHER ELEMENT TO THE SAME ARRAY IF IT'S NOT PRESENT 
> db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":12}}}); 
> db.stack.findOne() 
{ "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here", 
    "trips" : [ 
     { "loc" : [ 
       { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:35" 
       }, { "lat" : 21.321231, 
        "lng" : 16.8783234, 
        "updated_at" : "Mon May 10 2010 15:24:24" 
       }, { "lat" : 11, 
        "lng" : 11 
       }, { "lat" : 11, 
        "lng" : 12 
       } 
      ], "name" : "2010-05-10" 
     }, 
     { "name" : "2010-05-08", 
      "loc" : [ ... ] 
    } ] } 
+0

प्रतिक्रिया @ एंथनी मोरेली के लिए धन्यवाद। मैंने $ addToSet की कोशिश की और पहली बार एक यात्रा डालने के लिए अपरर्ट = सत्य में पास होना पड़ा। जब मैंने यात्रा नाम को किसी और चीज़ में बदल दिया, तो यह वास्तव में वर्तमान दस्तावेज़ का उपयोग करने के बजाय एक नया दस्तावेज़ बनाता है। हम कैसे निर्दिष्ट कर सकते हैं कि "यात्राएं" एक सरणी है? – Grnbeagle

+0

आपने विशेष रूप से कौन सी क्वेरी चलाई? $ addToSet केवल सरणी के साथ काम करता है, इसलिए मुझे नहीं लगता कि विनिर्देश समस्या है। – nearlymonolith

+0

मैंने आपकी क्वेरी बिल्कुल ठीक की, और यह एक दस्तावेज़ नहीं बनाया, इसलिए मैं upsert = true में पारित किया। यह पहला दस्तावेज़ बनाता है, जब यह दूसरी बार दौड़ता है, तो उसने इसे पिछले एक में जोड़ने के बजाय दूसरा दस्तावेज़ बनाया .. – Grnbeagle

संबंधित मुद्दे