MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

उपयोगकर्ता जानकारी के साथ MongoDB क्वेरी टिप्पणियां

समस्याएं

जैसा पहले लिखा गया था , अधिक एम्बेडिंग करते समय कई समस्याएं होती हैं:

समस्या 1:बीएसओएन आकार सीमा

इस लेखन के समय तक, बीएसओएन दस्तावेज़ 16 एमबी तक सीमित हैं . यदि वह सीमा समाप्त हो जाती है, तो MongoDB एक अपवाद फेंक देगा और आप बस अधिक टिप्पणियां नहीं जोड़ सकते हैं और सबसे खराब स्थिति में (उपयोगकर्ता-) नाम या तस्वीर भी नहीं बदल सकते हैं यदि परिवर्तन दस्तावेज़ के आकार को बढ़ा देगा।

समस्या 2:क्वेरी सीमाएं और प्रदर्शन

कुछ शर्तों के तहत टिप्पणियों की सरणी को क्वेरी या सॉर्ट करना आसानी से संभव नहीं है। कुछ चीजों के लिए काफी महँगे एकत्रीकरण की आवश्यकता होगी, दूसरों के लिए बल्कि जटिल बयानों की।

जबकि कोई यह तर्क दे सकता है कि एक बार प्रश्न हो जाने के बाद, यह कोई समस्या नहीं है, मैं अलग होना चाहता हूं। सबसे पहले, एक क्वेरी जितनी जटिल होती है, उसे ऑप्टिमाइज़ करना उतना ही कठिन होता है, डेवलपर और बाद में MongoDBs क्वेरी ऑप्टिमाइज़र दोनों के लिए। डेटा मॉडल और प्रश्नों को सरल बनाने, एक उदाहरण में 100 के कारक द्वारा प्रतिक्रियाओं को तेज करने के साथ मुझे सबसे अच्छे परिणाम मिले हैं।

स्केलिंग करते समय, जटिल और/या महंगी क्वेरी के लिए आवश्यक संसाधन एक सरल डेटा मॉडल की तुलना में और क्वेरी के अनुसार पूरी मशीन तक हो सकते हैं।

समस्या 3:रख-रखाव

अंतिम लेकिन कम से कम आप अपने कोड को बनाए रखने में समस्याओं का सामना कर सकते हैं। अंगूठे के एक साधारण नियम के रूप में

इस संदर्भ में, "महंगा" दोनों पैसे (पेशेवर परियोजनाओं के लिए) और समय (शौक परियोजनाओं के लिए) को संदर्भित करता है।

(मेरा!) समाधान

यह बहुत आसान है:अपने डेटा मॉडल को सरल बनाएं। नतीजतन, आपके प्रश्न कम जटिल और (उम्मीद के मुताबिक) तेज हो जाएंगे।

चरण 1:अपने उपयोग के मामलों की पहचान करें

यह मेरे लिए एक बेतुका अनुमान होने जा रहा है, लेकिन यहां महत्वपूर्ण बात यह है कि आपको सामान्य तरीका दिखाना है। मैं आपके उपयोग के मामलों को इस प्रकार परिभाषित करूंगा:

  1. किसी दिए गए पोस्ट के लिए, उपयोगकर्ताओं को टिप्पणी करने में सक्षम होना चाहिए
  2. किसी दिए गए पोस्ट के लिए, लेखक और टिप्पणियों के साथ-साथ टिप्पणीकारों और लेखकों का उपयोगकर्ता नाम और उनकी तस्वीर दिखाएं
  3. किसी दिए गए उपयोगकर्ता के लिए, नाम, उपयोगकर्ता नाम और चित्र बदलना आसानी से संभव होना चाहिए

चरण 2:अपने डेटा को तदनुसार मॉडल करें

उपयोगकर्ता

सबसे पहले, हमारे पास एक सीधा उपयोगकर्ता मॉडल है

{
  _id: new ObjectId(),
  name: "Joe Average",
  username: "HotGrrrl96",
  picture: "some_link"
}

यहां कुछ भी नया नहीं है, केवल पूर्णता के लिए जोड़ा गया है।

पोस्ट

{
  _id: new ObjectId()
  title: "A post",
  content: " Interesting stuff",
  picture: "some_link",
  created: new ISODate(),
  author: {
    username: "HotGrrrl96",
    picture: "some_link"
  }
}

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

टिप्पणियां

{
  _id: new ObjectId(),
  post: someObjectId,
  created: new ISODate(),
  commenter: {
    username: "FooBar",
    picture: "some_link"
  },
  comment: "Awesome!"
}

पोस्ट के समान ही, हमारे पास पोस्ट प्रदर्शित करने के लिए सभी आवश्यक डेटा होते हैं।

प्रश्न

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

टिप्पणी जोड़ना

यह अब बिल्कुल सीधा है।

किसी पोस्ट के लिए सभी या कुछ टिप्पणियां प्राप्त करना

सभी टिप्पणियों के लिए

db.comments.find({post:objectIdOfPost})

3 सबसे आखिरी टिप्पणियों के लिए

db.comments.find({post:objectIdOfPost}).sort({created:-1}).limit(3)

तो उपयोगकर्ता नाम और चित्रों सहित एक पोस्ट और सभी (या कुछ) टिप्पणियों को प्रदर्शित करने के लिए हम दो प्रश्नों पर हैं। आपको पहले की आवश्यकता से अधिक, लेकिन हमने आकार सीमा को दरकिनार कर दिया और मूल रूप से आपके पास प्रत्येक पोस्ट के लिए अनिश्चित संख्या में टिप्पणियां हो सकती हैं। लेकिन चलिए कुछ वास्तविक करते हैं

नवीनतम 5 पोस्ट और उनकी नवीनतम 3 टिप्पणियां प्राप्त करना

यह दो चरणों वाली प्रक्रिया है। हालाँकि, उचित अनुक्रमण के साथ (उस पर बाद में वापस आएगा) यह अभी भी तेज़ होना चाहिए (और इसलिए संसाधन की बचत):

var posts = db.posts.find().sort({created:-1}).limit(5)
posts.forEach(
  function(post) {
    doSomethingWith(post);
    var comments = db.comments.find({"post":post._id}).sort("created":-1).limit(3);
    doSomethingElseWith(comments);
  }
)

किसी दिए गए उपयोगकर्ता की सभी पोस्ट नवीनतम से सबसे पुराने और उनकी टिप्पणियों के क्रम में प्राप्त करें

var posts = db.posts.find({"author.username": "HotGrrrl96"},{_id:1}).sort({"created":-1});
var postIds = [];
posts.forEach(
  function(post){
    postIds.push(post._id);
  }
)
var comments = db.comments.find({post: {$in: postIds}}).sort({post:1, created:-1});

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

उपयोगकर्ता नाम बदलें

यह संभवतः एक दुर्लभ उपयोग का मामला है जिसे निष्पादित किया गया है। हालांकि, उक्त डेटा मॉडल के साथ यह बहुत जटिल नहीं है

सबसे पहले, हम उपयोगकर्ता दस्तावेज़ बदलते हैं

db.users.update(
  { username: "HotGrrrl96"},
  {
    $set: { username: "Joe Cool"},
    $push: {oldUsernames: "HotGrrrl96" }
  },
  {
    writeConcern: {w: "majority"}
  }
);

हम पुराने उपयोगकर्ता नाम को एक अनुसार सरणी में धकेलते हैं। यह एक सुरक्षा उपाय है यदि निम्नलिखित कार्यों में कुछ गलत हो जाता है। इसके अलावा, यह सुनिश्चित करने के लिए कि डेटा टिकाऊ है, हम लिखने की चिंता को एक उच्च स्तर पर सेट करते हैं।

db.posts.update(
  { "author.username": "HotGrrrl96"},
  { $set:{ "author.username": "Joe Cool"} },
  {
    multi:true,
    writeConcern: {w:"majority"}
  }
)

यहां कुछ खास नहीं है। टिप्पणियों के लिए अद्यतन विवरण काफी समान दिखता है। हालांकि उन प्रश्नों में कुछ समय लगता है, लेकिन उन्हें शायद ही कभी निष्पादित किया जाता है।

सूचकांक

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

पोस्ट

db.posts.createIndex({"author.username":1,"created":-1})

टिप्पणियां

db.comments.createIndex({"post":1, "created":-1})

निष्कर्ष

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

उपरोक्त समाधान के साथ, आप मूल रूप से असीमित मापनीयता और डेटा से निपटने के अधिक सरल तरीके के विरुद्ध कुछ गति (यदि!) का व्यापार करते हैं।

हठ।



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. ऑटोलैड कॉन्फ़िगरेशन MongoDB कक्षाओं को लोड नहीं करता है

  2. PHP में MongoDB '$or' और regex

  3. MongoEngine का उपयोग करके क्रमबद्ध करें?

  4. MongoDB SSL प्रतिकृति सेटअप समस्याएँ - असमर्थित प्रमाणपत्र

  5. $substr . का उपयोग करके क्षेत्र द्वारा मोंगोडब समूह