2012-05-20 10 views
18

एक सरल मोंगो दस्तावेज़ संरचना को ध्यान में रखते ही सेट:MongoDB: upserting: मूल्य अगर दस्तावेज़ डाला जा रहा है

{_ id, फ़र्स्टटाइम, lastTime}

ग्राहक एक ज्ञात आईडी के साथ एक दस्तावेज़ सम्मिलित करना होता है, या एक मौजूदा दस्तावेज़ अद्यतन करें। 'आखिरी समय' हमेशा कुछ नवीनतम समय पर सेट किया जाना चाहिए। 'फर्स्टटाइम' के लिए, यदि कोई दस्तावेज़ डाला जा रहा है, तो 'firstTime' को वर्तमान समय पर सेट किया जाना चाहिए। हालांकि, अगर दस्तावेज़ पहले ही बनाया गया है, तो 'फर्स्टटाइम' अपरिवर्तित बनी हुई है। मैं इसे पूरी तरह से अप्सर्ट (लुकअप से बचने के लिए) करना चाहता हूं।

मैंने http://www.mongodb.org/display/DOCS/Updating को क्रॉल किया है, लेकिन मुझे नहीं लगता कि यह विशेष ऑपरेशन कैसे किया जा सकता है।

मुझे विश्वास नहीं है कि यह कुछ अनुचित है, $ पुश और $ addToSet ऑपरेशंस हैं जो प्रभावी रूप से सरणी फ़ील्ड पर ऐसा करते हैं, बस कुछ भी नहीं जो साधारण फ़ील्ड पर समान होता है। ऐसा लगता है कि $ setIf ऑपरेशन की तरह कुछ होना चाहिए।

+0

* यदि दस्तावेज़ पहले ही बनाया गया है, तो फ़ील्ड अपरिवर्तित बनी रहती है * इसे अपरर्ट नहीं कहा जाता है (जैसा कि आपके शीर्षक में है) –

+0

@ ओम-नाम-नाम मैंने सबसे सरल मामला रेखांकित किया है, मैंने अपडेट किया है विवरण, इसलिए एक ऐसा क्षेत्र है जिसे हमेशा अद्यतन किया जा रहा है। –

+1

ऐसा लगता है कि इस सुविधा को 2.4 के लिए लक्षित किया गया है: https://jira.mongodb.org/browse/SERVER-340 – JohnnyHK

उत्तर

27

मैं ठीक उसी समस्या में पड़ गए और वहाँ < 2.4 तथापि 2.4 के बाद से $ setOnInsert ऑपरेटर के लिए कोई सरल उपाय था चलो आप ठीक वही करते हैं।

db.collection.update(<query>, 
         { $setOnInsert: { "firstTime": <TIMESTAMP> } }, 
         { upsert: true } 
        ) 

अधिक जानकारी के लिए 2.4 release notes of setOnInsert देखें।

1

केवल एक अपर्ट के साथ ऐसा करने का कोई तरीका नहीं है। आपको इसे 2 ऑपरेशंस के रूप में करना होगा - पहले दस्तावेज़ डालने का प्रयास करें, यदि यह पहले से मौजूद है तो सम्मिलन _id अनुक्रमणिका पर डुप्लिकेट कुंजी उल्लंघन के कारण विफल हो जाएगा। फिर आप अंतिम समय को सेट करने के लिए एक अद्यतन ऑपरेशन करते हैं।

+0

आईएमएचओ, यह सिंक्रोनस लुकअप के लिए पहला ऑपरेशन रकम, उद्देश्य, कर और इंतजार कर देगा। मुझे "विफल होने का प्रयास" में कोई अंतर नहीं दिख रहा है और ढूंढें और अपडेट करें ... –

+1

कई समवर्ती लेखकों के साथ खोज और अद्यतन और अद्यतन दृष्टिकोण के साथ एक दौड़ स्थिति है। यदि कोई अन्य लेखक उस दस्तावेज़ में आता है और बनाता/बदलता है जब पहले धागे ने पढ़ा था और जब यह लिखता है, तो आप लिखने के लिए अन्य धागे को ओवरराइड कर सकते हैं। – stbrody

+0

यही कारण है कि मैं इसे एक ही लिखने() ऑपरेशन में चाहता हूं, इसलिए मोंगो को इसे परमाणु रूप से निष्पादित करने के लिए कहें। –

1

जब मौजूदा सामग्री के आधार पर दस्तावेजों Upsert करने का प्रयास कर मैं एक बहुत ही इसी तरह की समस्या का सामना किया - शायद इस समाधान आप के लिए भी काम करेगा:

अपने रिकॉर्ड से _ id विशेषता निकालने का प्रयास करें और केवल क्वेरी में इसका इस्तेमाल करते हैं अपने अद्यतन की भाग (आप अनुवाद करना pymongo बात से होगा ...)

myid = doc.get('_id') 
del doc['_id'] 
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True) 
संबंधित मुद्दे