2009-10-09 32 views
24

में अद्वितीय बाधाएं अद्वितीय बाधाओं को लागू करने के लिए कोई तकनीक/प्रस्ताव हैं? हां, हम कुंजी बना सकते हैं जो अनूठा है, लेकिन हम कुंजी और चाबियाँ नहीं बदल सकते हैं और यह दृष्टिकोण जटिल सत्यापन (अलग अनन्य लॉगिन, अलग अद्वितीय ईमेल इत्यादि ...)couchdb

उदाहरण के लिए, एक खाता होना चाहिए अद्वितीय लॉगिन और ईमेल है। एक प्रमुख इस क्षेत्रों से पाने विसंगति का परिणाम देगा:

key1: "[email protected]", { email: "[email protected]", login: "john"} 
key2: "[email protected]", { email: "[email protected]", login: "mary"} 

अच्छा लग रहा है, लेकिन:

key1: "[email protected]", { email: "[email protected]", login: "mary"} 
key2: "[email protected]", { email: "[email protected]", login: "mary"} 

ओह, अब हम प्रवेश के साथ 2 खाते हैं: "मैरी"

उत्तर

13

यह कॉच डीबी के कम मजेदार बिट्स में से एक है। अद्वितीय फ़ील्ड को संभालने के लिए मैंने पाया है कि सबसे अच्छा तरीका (जैसे आपके उपयोगकर्ता उदाहरण में) कुंजी के घटक के रूप में अद्वितीय मानों के साथ "पॉइंटर" दस्तावेज बनाना है, और फिर उनको अद्वितीय मानों का दावा करने के लिए उपयोग करें। ऐसा करने का महत्वपूर्ण हिस्सा प्राथमिक दस्तावेज़ के लिए अनुमानित कुंजी है, फिर प्राथमिक को बचाने से पहले अद्वितीय फ़ील्ड दावे दस्तावेजों को सहेजना (और मुख्य विवादों को प्राथमिक दस्तावेज़ को सहेजने से रोकना)।

एक अद्वितीय उपयोगकर्ता नाम और अद्वितीय ईमेल के साथ एक उपयोगकर्ता को देखते हुए, अपनी प्राथमिक दस्तावेज इस प्रकार दिखाई देंगे:

user-username-kurt: { primary_doc: "user-1234" } 
[email protected]: { primary_doc: "user-1234" } 
user-username-petunia: { primary_doc: "user-9876" } 
[email protected]: { primary_doc: "user-9876" } 

बनाना या अद्यतन:

user-1234: { username: "kurt", email: "[email protected]" } 
user-9876: { username: "petunia", email: "[email protected]" } 

अद्वितीय क्षेत्र संकेत कुछ इस तरह दिखेगा उपयोगकर्ता इन चरणों को ले जाएगा:

  1. अपने उपयोगकर्ता दस्तावेज़ को तैयार करें, इसके लिए एक कुंजी उत्पन्न करें cessary
  2. बचाना प्रत्येक के लिए एक "सूचक" दस्तावेज़ अद्वितीय क्षेत्र बदल
  3. हैं उन में से किसी को बचाने के विफल रहता है, बंद करो और त्रुटियों
  4. ठीक सहेजें प्राथमिक उपयोगकर्ता दस्तावेज़

चरण 3 कुछ सोचा ले जाएगा। उदाहरण के लिए, आप उन फ़ील्ड के लिए अनन्य मानों का दावा नहीं करना चाहेंगे जो बदले नहीं गए हैं। आप कर सकते हैं, लेकिन फिर आपको उस मामले को संभालने के लिए कुछ अतिरिक्त तर्क देना होगा जहां आप उस उपयोगकर्ता के लिए मान का दावा कर रहे हैं जो पहले से ही उस मान का मालिक है।

चरण 3 लोगों को पुराने दावों के मूल्यों को लेने के लिए एक अच्छी जगह होगी। यदि एक उपयोगकर्ता ने उपयोगकर्ता नाम कर्ट को "जारी" किया है, उदाहरण के लिए, मैं यह सत्यापित करने के बाद कि यह अब उपयोग में नहीं है, मैं अपनी नई कुंजी को इंगित करने के लिए उस विशेष दस्तावेज़ को अपडेट कर सकता हूं। विकल्प बदलते समय अद्वितीय मूल्यों को स्पष्ट करना है। मुझे यकीन नहीं है कि वास्तव में कम काम कौन सा होगा। बालों का दावा करने वाले मूल्यों को छोड़कर मुझे सबसे ज्यादा समझदारी मिलती है।

इस समाधान के बारे में दिलचस्प बात यह है कि आपको बनाए जाने के बाद किसी भी चीज़ के लिए उन पॉइंटर दस्तावेज़ों का उपयोग करने की आवश्यकता नहीं है। आप अपने उपयोगकर्ता दस्तावेज़ों पर सामान्य के रूप में दृश्य बना सकते हैं, और ईमेल या उपयोगकर्ता नाम से पूछताछ के लिए उनका उपयोग कर सकते हैं।

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

+3

हाँ, यह एक समाधान है, लेकिन व्यक्तिगत रूप से मैं रेडिस के साथ लॉक करना पसंद करता हूं। इस तरह के समाधान अजीब लग रहे हैं जब डेवलपर्स आरडीबीएमएस दुनिया से आ रहे हैं। आरडीबीएमएस के बाद कॉच डीबी अलग है, लेकिन क्या हमें सभी मौजूदा प्रथाओं को खारिज कर देना चाहिए? कोई एसीआईडी ​​और ताले नहीं हैं, लेकिन इन सभी चीजों के बिना आराम करना और केवल एप्लिकेशन लिखना असंभव है। कॉच डीबी की प्रमुख विशेषताएं गायब हैं और यह दुखद है। – Sam

+0

दस्तावेज़ आईडी में जोड़ने से पहले अद्वितीय मान को छेड़छाड़ करना उन विशेषताओं को जोड़ने के लिए अधिक सुविधाजनक बनाता है जिनमें विशेष वर्ण हो सकते हैं। –

+2

ध्यान दें कि यदि आप चीजों को बहु-मास्टर अनुकूल रखने की योजना बनाते हैं, तो बिंदु 2।** ** ** विफल नहीं होगा जब तक कि * वर्तमान * नोड पर कुंजी पहले से मौजूद न हो। कुंजी नोड पर केवल अनूठी हैं जिन पर वे मौजूद हैं। इस समस्या के लिए एक सरल क्लस्टर अनुकूल समाधान के लिए रैफी एम के जवाब देखें। – user1973386

9

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

यदि आप केवल एक सर्वर सर्वर के बारे में परवाह करते हैं तो अनुमान लगाया जा सकता है कि आप अपने सोफेज को नेटवर्किंग समर्थन के साथ पुनर्निर्माण कर सकते हैं और अपने validate_doc_update() फ़ंक्शन में एक http क्वेरी निष्पादित कर सकते हैं जो डीबी के खिलाफ एक क्वेरी करेगा, यह देखने के लिए कि ईमेल पता पहले से ही उपयोग हो चुका है या नहीं और यदि ऐसा है तो अद्यतन विफल। सत्यापन तंत्र के बारे में अधिक जानकारी के लिए here देखें। मैं ऐसा करने की अनुशंसा नहीं करता, इसके बजाय मैं आईडी फ़ील्ड में सभी विशिष्टता को एम्बेड करता हूं (या तो सीधे या हैशिंग के माध्यम से) और यदि उपयोगकर्ता ने उस पर कुछ भी बदल दिया है तो बस डॉक्टर को स्थानांतरित करने के साथ सौदा करें।

+0

यह चीजों को करने का एक दुष्ट तरीका है – Prospero

+1

यह एक अच्छा दृष्टिकोण है जब तक कि अद्वितीय फ़ील्ड मान (उदाहरण के लिए ईमेल पता) बदल नहीं सकता है। फिर आपको एक नई आईडी के लिए फिर से प्रयास करना होगा। चूंकि आप किसी मौजूदा रिकॉर्ड की आईडी नहीं बदल सकते हैं, इसलिए आपको एक नया रिकॉर्ड बनाना होगा और पुराने को हटाना होगा, जो तब इसे एक परिपत्र समस्या बनाता है। –

19

कोर उत्तर

संरचना अपने पदों/डालता दस्तावेज है जो क्षेत्र आप इस प्रकार अद्वितीय रखना चाहते है के लिए:

  1. एक view बनाएँ। मानचित्र फ़ंक्शन उस क्षेत्र का उपयोग करें जिसे आप कुंजी के रूप में अद्वितीय रूप से लागू करना चाहते हैं। मूल्य कुछ भी नहीं हो सकता है। अपनी प्रत्येक कुंजी के लिए गणना प्राप्त करने के लिए फ़ंक्शन को कम करें। सबसे अच्छा तरीका (प्रदर्शन के लिए) _count फ़ंक्शन को कम करने के लिए उपयोग करना है।

  2. तुरंत बाद PUT/पोस्ट एक नए डेटाबेस में दस्तावेज़, लौटे id और rev और प्राप्त/yourdb/_design/yourapp/_view/VIEWNAME? समूह हड़पने = सच & key = "मूल्य -अप-अनूठा-फ़ील्ड-से-चरण -1 "।

  3. पिछले का परिणाम प्राप्त आप से अन्य गिनती मूल्य देता है, तो आप सिर्फ एक नकली डाला। तत्काल DELETE/yourdb/आईडी-से-चरण -2? Rev = rev-from-step-2

  4. आराम


असहज उदाहरण

कहते हैं कि तुम उपयोगकर्ता खातों भंडारण कर रहे हैं और क्या आप वाकई ईमेल पते अद्वितीय है बनाना चाहते चलें, लेकिन आप (यह दस्तावेज़ आईडी बनाने के लिए नहीं करना चाहते हैं जो कोई भी कारण के लिए)। ऊपर वर्णित ईमेल पते पर विशिष्टता की तुरंत जांच करने के लिए एक दृश्य बनाएं। आइए इसे ईमेल पर कॉल करें। इसमें नक्शा फ़ंक्शन संभवतः इस तरह के समान होगा ...

function(doc) { 
    if(doc.type === 'account') { 
    emit(doc.email, 1); 
    } 
} 

और बस _countके रूप में कार्य कम। यदि आप से ऊपर _sum जैसे काम करते हैं तो भी काम करेंगे। जैसा कि ऊपर दिखाया गया है, अपने दस्तावेज़ पर type फ़ील्ड रखने और जांचना सिर्फ एक सम्मेलन है लेकिन मुझे कभी-कभी यह उपयोगी लगता है। यदि आप जो भी भंडारण कर रहे हैं वह उपयोगकर्ता खाते हैं, तो शायद आपको इसकी आवश्यकता नहीं है।

अब कहते हैं कि हम तो जैसे एक दस्तावेज़ डालने कर रहे हैं की सुविधा देता है ...

POST /mydb/ 
{ 
    "name": "Joe", 
    "email": "[email protected]" 
} 

और CouchDB कुछ तरह के साथ जवाब देंगे ...

{ 
    ok: true, 
    id: 7c5c249481f311e3ad9ae13f952f2d55, 
    rev: 1-442a0ec9af691a6b1690379996ccaba6 
} 

चेक अगर हम अब से अधिक है को देखने के लिए डेटाबेस में एक [email protected] ...

GET /mydb/_design/myapp/_view/emails/?group=true&key="[email protected]" 

और कॉच डीबी कुछ ऐसा जवाब देगा ...

{ 
    rows: [ 
    { 
     key: "[email protected]", 
     value: 1 
    } 
    ] 
} 

तो value कि उत्तर में 1 के अलावा और कुछ है, तो आप शायद सिर्फ एक नकली ईमेल डाला। तो दस्तावेज़ को हटाएं और की पंक्तियों के साथ एक त्रुटि लौटाएं ईमेल पता विशिष्ट होना चाहिए, जो एक सामान्य SQL डेटाबेस प्रतिक्रिया या जो भी आप चाहते हैं।

हटाने कुछ इस तरह जाना होगा ...

DELETE /mydb/7c5c249481f311e3ad9ae13f952f2d55?rev=1-442a0ec9af691a6b1690379996ccaba6 

लघु चर्चा (यदि आप परवाह)

आप एक अच्छे पुराने * एसक्यूएल पृष्ठभूमि से आ रहे हैं, इस गलत और अजीब लग रहा है। इससे पहले कि आप इन बिंदुओं पर विचार करें। किसी क्षेत्र पर बाधा होने के कारण, जैसे विशिष्टता या कुछ और, स्कीमा का तात्पर्य है। कॉच डीबी स्कीमालेस है। * एसक्यूएल से आने का मतलब है कि आपको जिस तरह से लगता है उसे बदलना होगा। एसीआईडी ​​और ताले एकमात्र रास्ता नहीं हैं। कॉच डीबी बहुत लचीलापन और शक्ति के साथ आता है। आप जो भी चाहते हैं उसे प्राप्त करने के लिए आप इसका उपयोग अपने उपयोग के विवरण के विवरण पर निर्भर करते हैं और पारंपरिक संबंधपरक डेटाबेस सोच की सीमाओं से कितनी अच्छी तरह से बच सकते हैं।

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

आप उपरोक्त आप POST डॉक से पहले ई-मेल पता की विशिष्टता की जाँच करने के उदाहरण में परीक्षा जा सकता है। सावधान रहे!!यदि कई चीजें चल रही हैं, तो संभव है कि उसी ईमेल पते वाले दूसरे दस्तावेज़ को में के बाद डेटाबेस में डाला जा सके, आप जांचते हैं कि ईमेल मौजूद है या नहीं, से पहले आप POST करते हैं! यह आपको डुप्लिकेट ईमेल के साथ छोड़ देगा।

POST से पहले ईमेल पते के लिए चेक चलाने में कुछ भी गलत नहीं है। उदाहरण के लिए, यह एक अच्छा विचार है यदि आपका उपयोगकर्ता कोई फॉर्म भर रहा है और आप डेटाबेस में ईमेल फ़ील्ड मान को अजाक्स कर सकते हैं। आप उपयोगकर्ता को पूर्व-चेतावनी दे सकते हैं कि ईमेल पता मौजूद है या सबमिशन को रोकता है, आदि। हालांकि, सभी मामलों में, आपको भी के बाद POST दस्तावेज़ के बाद विशिष्टता की जांच करनी चाहिए। फिर आवश्यकतानुसार प्रतिक्रिया दें। यूआई पक्ष के परिप्रेक्ष्य से, ऊपर दिए गए कदम एक विशिष्ट * एसक्यूएल डेटाबेस पक्की से प्राप्त विशिष्टता बाधा पर प्राप्त परिणाम से अलग नहीं होंगे।

क्या कुछ भी गलत हो सकता है? हाँ। इस पर विचार करो। मान लें [email protected] डेटाबेस में पहले से मौजूद नहीं है। डेटाबेस में सहेजे जाने के लिए लगभग एक ही समय में दो दस्तावेज़ आते हैं। डॉक्टर एक, POSTed है तो डॉक्टर बीPOSTed है, लेकिन इससे पहले कि हम डॉक्टर एकPOST के लिए विशिष्टता की जांच करने में सक्षम हैं। तो अब जब हम डॉक एPOST के लिए विशिष्टता की जांच करते हैं, तो हम देखते हैं कि [email protected] डेटाबेस में दो बार है। तो, हम इसे हटा देंगे और समस्या के साथ रिपोर्ट करेंगे। लेकिन इससे पहले कि हम डॉक ए हटा सकते हैं, डॉक बी के लिए विशिष्टता जांच भी होती है, [email protected] के लिए समान गणना मान प्राप्त करने से पहले भी होता है। अब POSTs दोनों को खारिज कर दिया जाएगा, भले ही [email protected] मूल रूप से डेटाबेस में नहीं था! दूसरे शब्दों में, यदि मिलान करने वाले मूल्य वाले दो दस्तावेज़ लगभग एक ही समय में आपके ऐप में आते हैं, तो संभव कि वे एक-दूसरे को POSTs देख सकते हैं और गलती से निष्कर्ष निकाल सकते हैं कि वे जो मान लेते हैं वह पहले ही डेटाबेस में है! हम वास्तव में इसे रोक नहीं सकते क्योंकि CouchDB में कोई पारंपरिक आरडीबी शैली लॉक नहीं है। लेकिन उस छोटी कीमत के बदले में, हमें मास्टर-मास्टर प्रतिकृति और अन्य शांत सामानों का एक टन मिलता है। मैं इसे ले जाऊँगा! और यदि यह आपके कार्यान्वयन के लिए एक बड़ी समस्या है, तो आप किसी प्रकार के पुन: प्रयास तंत्र को लागू करके इसे संबोधित करने का प्रयास कर सकते हैं।

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

+5

संदर्भ में यह करने के लिए: _ "लेकिन आप इसे (जो भी कारण के लिए) दस्तावेज़ आईडी बनाने के लिए नहीं करना चाहती" _ मैं सिर्फ करते रहे कि ईमेल और/या _ id के रूप में उपयोगकर्ता नाम का उपयोग अवांछनीय है चाहते हैं। यदि कोई उपयोगकर्ता अपना ईमेल या उपयोगकर्ता नाम बदलता है तो वह उस दस्तावेज़ आईडी के बाहरी संदर्भ को तोड़ देगा (और शायद एक गुच्छा होगा)। –

+2

सच है। यह मुझे लगता है कि "जो भी कारण के लिए" के तहत आता है। :) –

+2

खैर, यह BTW एक अच्छा कारण :) है - मैं अपने लघु चर्चा एक बहुत सराहना की थी। बहुत अच्छी जानकारी। –

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