আমি মঙ্গোডিবি-তে সমতুল্য এসকিউএল সম্পাদন করব কীভাবে?


498

আমি মঙ্গোডিবি-তে সমতুল্য এসকিউএল সম্পাদন করব কীভাবে?

উদাহরণস্বরূপ বলুন যে আপনার দুটি সংগ্রহ (ব্যবহারকারী এবং মন্তব্য) রয়েছে এবং আমি প্রত্যেকটির ব্যবহারকারীর তথ্যের সাথে পিড = 444 সহ সমস্ত মন্তব্য টানতে চাই।

comments
  { uid:12345, pid:444, comment="blah" }
  { uid:12345, pid:888, comment="asdf" }
  { uid:99999, pid:444, comment="qwer" }

users
  { uid:12345, name:"john" }
  { uid:99999, name:"mia"  }

একটি নির্দিষ্ট ক্ষেত্রের সাথে সমস্ত মন্তব্য (যেমন। ... সন্ধান করুন (id পিড: 444 one)) এবং একযোগে প্রতিটি মন্তব্যের সাথে সম্পর্কিত ব্যবহারকারীর তথ্য কী টানানোর কোনও উপায় আছে?

এই মুহুর্তে, আমি প্রথমে আমার মতামতগুলির সাথে মিলে যায় এমন মন্তব্যগুলি পেয়ে যাচ্ছি, তারপরে ফলাফলের সেটটিতে সমস্ত ইউডির সন্ধান করা, ব্যবহারকারীর জিনিসগুলি পাওয়া এবং মন্তব্যের ফলাফলের সাথে মার্জ করা। মনে হচ্ছে আমি এটি ভুল করছি।


35
এই প্রশ্নের শেষ উত্তর সম্ভবত সবচেয়ে প্রাসঙ্গিক, যেহেতু মঙ্গোডিবি ৩.২++ join লুকিং নামে একটি সংযুক্ত সমাধান প্রয়োগ করেছে। ভেবেছিলাম আমি এটিকে এখানে ধাক্কা দেব কারণ সম্ভবত সবাই নীচে পড়বেন না। stackoverflow.com/a/33511166/2593330
thefourtheye

6
সঠিক, $ দর্শনটি মঙ্গোডিবি ৩.২-এ প্রবর্তিত হয়েছিল। বিশদটি ডক্স.মোংডব.অর্গ / মাস্টার
এনডিবি

উত্তর:


306

মঙ্গো ৩.২ অনুসারে এই প্রশ্নের উত্তর বেশিরভাগ ক্ষেত্রে আর সঠিক নয়। সমষ্টি পাইপলাইনে যুক্ত হওয়া নতুন $ লুকিং অপারেটরটি মূলত বাম বাহিরের জোড়ার সাথে সমান:

https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup

ডক্স থেকে:

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

অবশ্যই মোঙ্গো হয় না একটি রিলেশনাল ডাটাবেস এবং devs $ লুকআপ জন্য নির্দিষ্ট ব্যবহারের ক্ষেত্রে সুপারিশ সতর্কতা অবলম্বন করা হচ্ছে, কিন্তু 3.2 করছেন যেমন অন্তত যোগদানের এখন MongoDB সঙ্গে সম্ভব।


@ ক্লেটন: এরপরে আরও দুটি সংগ্রহ কীভাবে হবে?
দীপেন দেদানিয়া

1
@ ডিপেনডেদানিয়া কেবলমাত্র পাইপলাইনে অতিরিক্ত $ দেখার পর্যায় যুক্ত করুন।
ক্লেটন গলিক

আমি ডান সংগ্রহের সাথে সম্পর্কিত আইডি দিয়ে বাম সংগ্রহের বিন্যাসে অ্যারের যে কোনও ক্ষেত্রে যোগদান করতে পারছি না? কেউ আমাকে সহায়তা করতে পারে ??
প্রীতেক সিং

1
আমি এ সম্পর্কে কিছুটা বিভ্রান্ত হয়েছি - "" "থেকে সংগ্রহের মধ্যে আপনি কেবলমাত্র কিছু নির্দিষ্ট নথি চান তা নির্দিষ্ট করার কোনও উপায় আছে কি না এটি স্বয়ংক্রিয়ভাবে একবারে ডিবিতে যুক্ত হয়ে যায়?
ব্যবহারকারী 3413723

শুধু ভাবছেন যে সাম্প্রতিকতম স্প্রিং ডেটা মঙ্গোডিবিতে 3.2 এর সমর্থন রয়েছে?
gtiwari333

142

অফিসিয়াল মোংডোব সাইটে এই পৃষ্ঠাটি ঠিক এই প্রশ্নের ঠিকানা দেয়:

https://mongodb-documentation.readthedocs.io/en/latest/ecosystem/tutorial/model-data-for-ruby-on-rails.html

আমরা যখন আমাদের গল্পের তালিকা প্রদর্শন করি তখন আমাদের গল্পটি পোস্ট করা ব্যবহারকারীর নাম দেখাতে হবে। আমরা যদি কোনও সম্পর্কযুক্ত ডাটাবেস ব্যবহার করি তবে আমরা ব্যবহারকারী এবং স্টোরগুলিতে একটি সংযুক্তি সম্পাদন করতে এবং আমাদের সমস্ত বস্তুগুলিকে একক কোয়েরিতে পেতে পারি। তবে মঙ্গোডিবি যোগদানের পক্ষে সমর্থন করে না এবং তাই সময়ে সময়ে কিছুটা অস্বীকৃতিও প্রয়োজন। এখানে, এর অর্থ 'ব্যবহারকারীর নাম' বৈশিষ্ট্যটি ক্যাচ করা।

রিলেশনাল পিউরিস্টরা ইতিমধ্যে অস্বস্তি বোধ করছে, যেন আমরা কোনও সার্বজনীন আইন লঙ্ঘন করছি। তবে আসুন আমরা মনে রাখি যে মোংগোডিবি সংগ্রহগুলি সম্পর্কিত টেবিলগুলির সমতুল্য নয়; প্রতিটি একটি অনন্য নকশা উদ্দেশ্য পরিবেশন করে। একটি সাধারণীকৃত টেবিল একটি পারমাণবিক, বিচ্ছিন্ন তথ্য উপাত্ত সরবরাহ করে। একটি দস্তাবেজ, সামগ্রিকভাবে একটি বিষয়টিকে আরও ঘনিষ্ঠভাবে উপস্থাপন করে। একটি সামাজিক বার্তা সাইটের ক্ষেত্রে, এটি যুক্তিযুক্ত হতে পারে যে কোনও ব্যবহারকারীর নাম পোস্ট করা হওয়ার গল্পটির অন্তর্নিহিত।


51
@ ডুডেলগ্রিনস্ন এটি সাধারণীকরণ এবং সম্পর্কিত ডেটাবেসগুলি থেকে একটি দৃষ্টান্তের স্থানান্তর। একটি নোএসকিউএল এর লক্ষ্য হ'ল খুব দ্রুত ডাটাবেস থেকে পড়া এবং লেখা। বিগডাটাতে আপনার কাছে ডিবিতে কম সংখ্যক অ্যাপ্লিকেশন এবং ফ্রন্ট এন্ড সার্ভার থাকবে। আপনি এক সেকেন্ডে কয়েক মিলিয়ন লেনদেন করার আশা করছেন। ডাটাবেস থেকে ভারী উত্তোলন অফলোড করে অ্যাপ্লিকেশন স্তরে রাখুন। আপনার যদি গভীর বিশ্লেষণের প্রয়োজন হয়, আপনি একটি সংহত কাজ চালান যা আপনার ডেটা একটি ওএলএপি ডাটাবেসে রাখে। যাইহোক আপনার ওলটিপি ডিবিএস থেকে আপনার অনেক গভীর কোয়েরি করা উচিত নয়।
স্নোবার্ট

18
@ ডুডেলগ্রিনসন আমার আরও বলা উচিত যে এটি প্রতিটি প্রকল্প বা ডিজাইনের জন্য নয়। আপনার যদি কোনও এসকিউএল টাইপ ডাটাবেসে কাজ করে তবে কেন এটি পরিবর্তন করবেন? আপনি যদি নো এসকিউএল নিয়ে কাজ করার জন্য আপনার স্কিমাটি ম্যাসেজ করতে না পারেন তবে তা করবেন না।
স্নোবার্ট

9
মাইগ্রেশন এবং একটি ক্রমাগত বিকশিত স্কীমা কোনও নুএসকিউএল সিস্টেমে পরিচালনা করাও অনেক সহজ।
জাস্টিন

14
যদি ব্যবহারকারীর ওয়েবসাইটে 3.540 টি পোস্ট থাকে এবং তিনি প্রোফাইলে তার ব্যবহারকারীর নাম পরিবর্তন করেন? প্রতিটি ব্যবহারকারীর নতুন নাম ব্যবহার করে আপডেট করা উচিত?
ইভো পেরেইরা

2
@ আইভোপিরিরা হ্যাঁ এবং ঠিক এই কারণেই এই উপায়ে মডেলিংয়ের তথ্য এড়ানো উচিত। একই নিদর্শন এবং এর পরিণতি ব্যাখ্যা করে এমন একটি নিবন্ধ রয়েছে: আপনার কখনই মঙ্গোবিবি ব্যবহার করা উচিত নয়
ওমিড

138

আমরা মঙ্গডব ক্লায়েন্ট কনসোলটি ব্যবহার করে কয়েকটি লাইনে একটি সহজ ফাংশন দিয়ে কেবলমাত্র একটি সংগ্রহের মধ্যে সমস্ত ডেটা মার্জ / যুক্ত করতে পারি এবং এখন আমরা কাঙ্ক্ষিত ক্যোয়ারীটি সম্পাদন করতে সক্ষম হতে পারি। একটি সম্পূর্ণ উদাহরণ নীচে,

.- লেখক:

db.authors.insert([
    {
        _id: 'a1',
        name: { first: 'orlando', last: 'becerra' },
        age: 27
    },
    {
        _id: 'a2',
        name: { first: 'mayra', last: 'sanchez' },
        age: 21
    }
]);

.- বিভাগসমূহ:

db.categories.insert([
    {
        _id: 'c1',
        name: 'sci-fi'
    },
    {
        _id: 'c2',
        name: 'romance'
    }
]);

.- বই

db.books.insert([
    {
        _id: 'b1',
        name: 'Groovy Book',
        category: 'c1',
        authors: ['a1']
    },
    {
        _id: 'b2',
        name: 'Java Book',
        category: 'c2',
        authors: ['a1','a2']
    },
]);

.- বই ধার

db.lendings.insert([
    {
        _id: 'l1',
        book: 'b1',
        date: new Date('01/01/11'),
        lendingBy: 'jose'
    },
    {
        _id: 'l2',
        book: 'b1',
        date: new Date('02/02/12'),
        lendingBy: 'maria'
    }
]);

.- চমক:

db.books.find().forEach(
    function (newBook) {
        newBook.category = db.categories.findOne( { "_id": newBook.category } );
        newBook.lendings = db.lendings.find( { "book": newBook._id  } ).toArray();
        newBook.authors = db.authors.find( { "_id": { $in: newBook.authors }  } ).toArray();
        db.booksReloaded.insert(newBook);
    }
);

.- নতুন সংগ্রহের ডেটা পান:

db.booksReloaded.find().pretty()

.- প্রতিক্রিয়া :)

{
    "_id" : "b1",
    "name" : "Groovy Book",
    "category" : {
        "_id" : "c1",
        "name" : "sci-fi"
    },
    "authors" : [
        {
            "_id" : "a1",
            "name" : {
                "first" : "orlando",
                "last" : "becerra"
            },
            "age" : 27
        }
    ],
    "lendings" : [
        {
            "_id" : "l1",
            "book" : "b1",
            "date" : ISODate("2011-01-01T00:00:00Z"),
            "lendingBy" : "jose"
        },
        {
            "_id" : "l2",
            "book" : "b1",
            "date" : ISODate("2012-02-02T00:00:00Z"),
            "lendingBy" : "maria"
        }
    ]
}
{
    "_id" : "b2",
    "name" : "Java Book",
    "category" : {
        "_id" : "c2",
        "name" : "romance"
    },
    "authors" : [
        {
            "_id" : "a1",
            "name" : {
                "first" : "orlando",
                "last" : "becerra"
            },
            "age" : 27
        },
        {
            "_id" : "a2",
            "name" : {
                "first" : "mayra",
                "last" : "sanchez"
            },
            "age" : 21
        }
    ],
    "lendings" : [ ]
}

আমি আশা করি এই লাইনগুলি আপনাকে সহায়তা করতে পারে।


2
আমি ভাবছি যদি এই একই কোডটি মতবাদ মঙ্গোদব ব্যবহার করে চালানো যায়?
অ্যাবড

4
যখন কোনও একটি রেফারেন্স অবজেক্ট আপডেট হয় তখন কী ঘটে? সেই আপডেটটি কি বইয়ের বস্তুটিতে স্বয়ংক্রিয়ভাবে প্রতিবিম্বিত হয়? নাকি সেই লুপটি আবার চালানো দরকার?
বালুপটন

14
আপনার ডেটা যতক্ষণ ছোট হবে এটি ঠিক আছে। এটি আপনার ক্লায়েন্টের প্রতিটি বইয়ের সামগ্রী আনতে চলেছে এবং তারপরে প্রতিটি বিভাগ, ndingণদান এবং লেখককে একের পর এক আনবে। আপনার বই যে মুহুর্তে হাজারে রয়েছে, এটি সত্যিই ধীর হয়ে যাবে। সম্ভবত আরও ভাল কৌশল হ'ল সমষ্টি পাইপলাইন ব্যবহার এবং একত্রীকরণে মার্জ হওয়া ডেটা আউটপুট। আমাকে আবার এটিতে ফিরে আসা যাক। আমি একটি উত্তর যোগ করব।
সন্দীপ গিরি

আপনি কি এই অন্যান্য উদাহরণের সাথে আপনার অ্যালগরিদমকে মানিয়ে নিতে পারেন? stackoverflow.com/q/32718079/287948
পিটার ক্রাউস

1
@ সন্দীপগিরি কীভাবে আমি সামগ্রিক পাইপলাইনটি করতে পারি যেহেতু পৃথক সংগ্রহের সত্যিকার অর্থেই নিবিড় ডেটাতে যোগদানের দরকার আছে ??
ইয়াসাইন আবদুল-রহমান

38

আপনি বর্ণিতভাবে এটি করতে হবে। মঙ্গোডিবি হ'ল একটি সম্পর্কহীন ডাটাবেস এবং এতে যোগদানের সমর্থন করে না।


4
কোনও স্কিল সার্ভার ব্যাকগ্রাউন্ড থেকে আসা ভুল পারফরম্যান্স অনুযায়ী বুদ্ধিমান মনে হচ্ছে, তবে এটি ডকুমেন্ট ডিবি দিয়ে খুব খারাপ নয়?
তেরজিটাইল

3
পাশাপাশি একটি SQL সার্ভার পটভূমি থেকে, আমি কৃতজ্ঞ হবে MongoDB এক বারেই একটি নতুন অনুসন্ধান জন্য (নির্বাচিত ফিরে ক্ষেত্রের সাথে) একটি 'ফলাফল সেট' গ্রহণ ইনপুট হিসাবে, অনেক SQL এর যে নেস্টেড প্রশ্নের মত
Stijn স্যান্ডার্সের

1
@terjetyl আপনি এটির জন্য সত্যিই পরিকল্পনা করতে হবে। আপনি কোন ক্ষেত্রগুলি সম্মুখ প্রান্তে উপস্থাপন করছেন, যদি এটি কোনও স্বতন্ত্র দৃষ্টিতে সীমিত পরিমাণ হয় তবে আপনি সেগুলি এমবেডড ডকুমেন্ট হিসাবে গ্রহণ করেন। কীটি যোগ দেওয়ার দরকার নেই। আপনি যদি গভীর বিশ্লেষণ করতে চান তবে আপনি এটি অন্য ডাটাবেসে সত্যের পরে করবেন। এমন একটি কাজ চালান যা সর্বোত্তম পারফরম্যান্সের জন্য ডেটাটিকে ওএলএপ কিউবে রূপান্তর করে।
স্নোবার্ট

4
মঙ্গো থেকে ৩.২ সংস্করণে বাম যোগদানগুলি সমর্থিত।
সোমনাথ মুলুক

18

যেহেতু অন্যরা ইঙ্গিত করেছে যে আপনি কোনও রিলেশনাল ডাটাবেস যা আপনি সত্যিকার অর্থেই করতে চান না তা থেকে একটি রিলেশনাল ডাটাবেস তৈরি করার চেষ্টা করছেন, যদি আপনার কাছে এমন একটি সমস্যা থাকে যে এখানে আপনাকে এটি করতে হয় তবে আপনি এটি সমাধান করতে পারেন। আমরা প্রথমে সংগ্রহের এ (বা আপনার ক্ষেত্রে ব্যবহারকারীদের) উপর একটি ভবিষ্যদ্বাণী করি এবং তারপরে আমরা প্রতিটি আইটেম হিসাবে পাই এবং তারপরে আমরা আমাদের দ্বিতীয় সংগ্রহে (আপনার ক্ষেত্রে মন্তব্যগুলি) অনুসন্ধান করতে অবজেক্ট প্রোপার্টি (আপনার ক্ষেত্রে ইউইডে) ব্যবহার করি যদি আমরা এটি খুঁজে পেতে পারে তবে আমাদের একটি মিল আছে এবং আমরা এটি দিয়ে মুদ্রণ করতে বা করতে পারি। আশা করি এটি আপনাকে এবং শুভ কামনা :)

db.users.find().forEach(
function (object) {
    var commonInBoth=db.comments.findOne({ "uid": object.uid} );
    if (commonInBoth != null) {
        printjson(commonInBoth) ;
        printjson(object) ;
    }else {
        // did not match so we don't care in this case
    }
});

আমরা বর্তমানে লুপ করছি এমন আইটেমটি এটি আবিষ্কার করবে না?
স্কারলিনস্কি

18

$ দর্শন , $ প্রকল্প এবং $ ম্যাচের সঠিক সংমিশ্রণের সাথে আপনি একাধিক পরামিতিগুলিতে একাধিক টেবিলগুলিতে যোগদান করতে পারেন। এটি একাধিকবার শৃঙ্খলিত হতে পারে কারণ এটি।

ধরুন আমরা নিম্নলিখিতটি করতে চাই ( রেফারেন্স )

SELECT S.* FROM LeftTable S
LEFT JOIN RightTable R ON S.ID =R.ID AND S.MID =R.MID WHERE R.TIM >0 AND 
S.MOB IS NOT NULL

পদক্ষেপ 1: সমস্ত টেবিল লিঙ্ক করুন

আপনি $ আপনি চান যতগুলি টেবিল সন্ধান করতে পারেন।

$ অনুসন্ধান - প্রশ্নের প্রতিটি টেবিলের জন্য একটি

$ বিনোদন - কারণ তথ্য সঠিকভাবে denormalised হয়, অন্য অ্যারে আবৃত

পাইথন কোড ..

db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "R"}

                        ])

পদক্ষেপ 2: সমস্ত শর্ত শর্ত নির্ধারণ করুন

$ প্রকল্প : সমস্ত শর্তাধীন বিবৃতি এখানে সংজ্ঞায়িত করুন, এবং আপনার পছন্দসই সমস্ত ভেরিয়েবল নির্বাচন করুন।

পাইথন কোড ..

db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "R"},

                        # define conditionals + variables

                        {"$project": {
                          "midEq": {"$eq": ["$MID", "$R.MID"]},
                          "ID": 1, "MOB": 1, "MID": 1
                        }}
                        ])

পদক্ষেপ 3: সমস্ত শর্তে যোগ দিন

$ মিল - OR বা AND ইত্যাদি ব্যবহার করে সমস্ত শর্তে যোগদান করুন There এগুলির বহুগুণ থাকতে পারে।

$ প্রকল্প : সমস্ত শর্ত শর্তহীন

পাইথন কোড ..

db.LeftTable.aggregate([
                        # connect all tables

                        {"$lookup": {
                          "from": "RightTable",
                          "localField": "ID",
                          "foreignField": "ID",
                          "as": "R"
                        }},
                        {"$unwind": "$R"},

                        # define conditionals + variables

                        {"$project": {
                          "midEq": {"$eq": ["$MID", "$R.MID"]},
                          "ID": 1, "MOB": 1, "MID": 1
                        }},

                        # join all conditionals

                        {"$match": {
                          "$and": [
                            {"R.TIM": {"$gt": 0}}, 
                            {"MOB": {"$exists": True}},
                            {"midEq": {"$eq": True}}
                        ]}},

                        # undefine conditionals

                        {"$project": {
                          "midEq": 0
                        }}

                        ])

টেবিল, শর্তসাপেক্ষে এবং যোগদানের অনেকগুলি সমন্বয় এই পদ্ধতিতে করা যেতে পারে।


17

এখানে একটি একটি উদাহরণ "যোগদান করুন" * অভিনেতা এবং চলচ্চিত্র সংগ্রহগুলি:

https://github.com/mongodb/cookbook/blob/master/content/patterns/pivot.txt

এটি .mapReduce()পদ্ধতিটি ব্যবহার করে

* join - ডকুমেন্ট-ভিত্তিক ডাটাবেসে যোগদানের একটি বিকল্প


19
-1, এটি দুটি সংগ্রহের ডেটাতে যোগ দিচ্ছে না। এটি চারপাশে একক সংগ্রহ (অভিনেতা) পিভোটিংয়ের ডেটা ব্যবহার করছে। সুতরাং যেগুলি কীগুলি এখন মূল্যবোধ এবং মানগুলি এখন কীগুলি ... একটি জিনের থেকে খুব আলাদা।
ইভান তেরান

12
ঠিক এটিই আপনাকে যা করতে হবে, মঙ্গোডিবি সম্পর্কযুক্ত নয় তবে নথিভিত্তিক। ম্যাপআরডিউস বড় পারফরম্যান্সের সাথে ডেটা নিয়ে খেলতে দেয় (আপনি ক্লাস্টার ইত্যাদি ব্যবহার করতে পারেন ....) তবে সাধারণ ক্ষেত্রেও এটি খুব কার্যকর!
থমাস ডেকাউস

14

আপনি 3.2 সংস্করণে অফার করা লুপআপ ব্যবহার করে মঙ্গোতে দুটি সংকলনে যোগ দিতে পারেন। আপনার ক্ষেত্রে ক্যোয়ারী হবে

db.comments.aggregate({
    $lookup:{
        from:"users",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})

অথবা আপনি ব্যবহারকারীদের সাথে সম্মানের সাথে যোগ দিতে পারেন তবে নীচে দেওয়া হিসাবে কিছুটা পরিবর্তন হবে।

db.users.aggregate({
    $lookup:{
        from:"comments",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})

এটি এসকিউএল-তে বাম এবং ডান যোগদানের মতোই কাজ করবে।


11

এটি আপনি কী করতে চাইছেন তার উপর নির্ভর করে।

আপনি বর্তমানে এটি একটি সাধারণ ডাটাবেস হিসাবে সেট আপ করেছেন, যা ভাল, এবং আপনি যেভাবে এটি করছেন তা যথাযথ।

তবে এটি করার অন্যান্য উপায়ও রয়েছে।

আপনার কাছে এমন একটি পোষ্ট সংগ্রহ হতে পারে যা ব্যবহারকারীদের রেফারেন্স সহ প্রতিটি পোস্টের জন্য মন্তব্যগুলিকে এম্বেড করেছে যেগুলি আপনি পুনরাবৃত্তভাবে জিজ্ঞাসা করতে জিজ্ঞাসা করতে পারেন। আপনি মন্তব্যগুলির সাথে ব্যবহারকারীর নাম সংরক্ষণ করতে পারেন, আপনি সেগুলিকে একটি নথিতে সংরক্ষণ করতে পারেন।

নোএসকিউএলযুক্ত জিনিসটি হ'ল এটি নমনীয় স্কিমা এবং খুব দ্রুত পড়া এবং লেখার জন্য তৈরি করা হয়েছে। সাধারণ বিগ ডেটা ফার্মে ডাটাবেসটি সবচেয়ে বড় বাধা, আপনার কাছে অ্যাপ্লিকেশন এবং ফ্রন্ট এন্ড সার্ভারের তুলনায় কম ডাটাবেস ইঞ্জিন থাকে ... সেগুলি আরও ব্যয়বহুল তবে আরও শক্তিশালী, হার্ড ড্রাইভের স্থান তুলনামূলকভাবে খুব সস্তা। সাধারণীকরণ স্থান বাঁচানোর চেষ্টা করার ধারণা থেকে আসে, তবে এটি আপনার ডাটাবেসগুলিকে জটিল যোগ দেওয়ার এবং সম্পর্কের অখণ্ডতা যাচাইকরণ, ক্যাসকেডিং অপারেশন সম্পাদন করার জন্য ব্যয় করে আসে। এর সবগুলিই বিকাশকারীদের কিছু মাথাব্যথা বাঁচায় যদি তারা ডাটাবেসটি সঠিকভাবে ডিজাইন করে।

নোএসকিউএল সহ, যদি আপনি স্বীকার করেন যে রিডানডেন্সি এবং স্টোরেজ স্পেসটি তাদের ব্যয়ের কারণে সমস্যা নেই (অতিরিক্ত ডেটা সঞ্চয় করার জন্য প্রসেসরের সময় প্রয়োজন হয় এবং অতিরিক্ত ড্রাইভের জন্য হার্ড ড্রাইভের ব্যয় হয়) তবে ডেনারমালাইজিং কোনও সমস্যা নয় (এম্বেড থাকা অ্যারেগুলির জন্য) কয়েক হাজার আইটেম এটি পারফরম্যান্সের সমস্যা হতে পারে তবে বেশিরভাগ সময় এটি কোনও সমস্যা নয়)। অতিরিক্তভাবে আপনার কাছে প্রতিটি ডাটাবেস ক্লাস্টারের জন্য বেশ কয়েকটি অ্যাপ্লিকেশন এবং ফ্রন্ট এন্ড সার্ভার থাকবে। তাদেরকে যোগদানের ভারী উত্তোলন করতে এবং ডাটাবেস সার্ভারগুলিকে পড়তে এবং লেখায় আটকে দিন।

টিএল; ডিআর: আপনি যা করছেন তা ঠিক আছে, এবং এটি করার অন্যান্য উপায়ও রয়েছে। কিছু দুর্দান্ত উদাহরণের জন্য মংডব ডকুমেন্টেশনের ডেটা মডেল নিদর্শনগুলি দেখুন। http://docs.mongodb.org/manual/data-modeling/


8
"স্থান সংরক্ষণের চেষ্টা করার ধারণা থেকে নরমালাইজেশন আসে" আমি এই প্রশ্নটি করি। আইএমএইচওর নরমালাইজেশন হ'ল অপ্রয়োজনীয়তা এড়ানোর ধারণা থেকে। বলুন আপনি কোনও ব্লগপোস্টের সাথে ব্যবহারকারীর নামও সঞ্চয় করেন। সে যদি বিয়ে করে? নরমালাইজড মডেলটিতে আপনাকে সমস্ত পোস্টের মধ্যে দিয়ে নাম লিখতে হবে এবং নাম পরিবর্তন করতে হবে। একটি সাধারণ মডেল আপনি সাধারণত এক রেকর্ড পরিবর্তন।
ড্যানিয়েল খান

@ ডানিয়েল খান অপ্রয়োজনীয়তা বাড়াতে এবং স্থান বাঁচানো একই ধরণের ধারণা, তবে পুনঃবিশ্লেষণে আমি একমত হই যে, এই নকশার মূল কারণ রিডানডেন্সি। আমি কথা বলব। নোটের জন্য ধন্যবাদ।
স্নোবার্ট

11

একটি স্পেসিফিকেশন রয়েছে যা প্রচুর ড্রাইভার সমর্থন করে যার নাম ডিবিআরএফ।

ডকুমেন্টগুলির মধ্যে রেফারেন্স তৈরির জন্য ডিবিআরএফ একটি আরও আনুষ্ঠানিক স্পেসিফিকেশন। ডিবিআরএফগুলি (সাধারণত) একটি সংগ্রহের নাম পাশাপাশি একটি অবজেক্ট আইডি অন্তর্ভুক্ত করে। বেশিরভাগ বিকাশকারী কেবল তখনই ডিবিআরএফগুলি ব্যবহার করেন যদি সংগ্রহটি একটি নথি থেকে অন্য দস্তাবেজে পরিবর্তন করতে পারে। যদি আপনার রেফারেন্সযুক্ত সংগ্রহ সবসময় একই থাকে তবে উপরে বর্ণিত ম্যানুয়াল রেফারেন্সগুলি আরও দক্ষ।

মঙ্গোডিবি ডকুমেন্টেশন থেকে নেওয়া: ডেটা মডেলগুলি> ডেটা মডেল রেফারেন্স> ডেটাবেস রেফারেন্স


11

$ দর্শন (সমষ্টি)

প্রসেসিংয়ের জন্য "যোগদান করেছেন" সংগ্রহ থেকে নথিগুলিতে ফিল্টার করার জন্য একই ডাটাবেজে একটি নিরীক্ষণ সংগ্রহের জন্য একটি বাম বাহির সংযুক্তি সম্পাদন করে। প্রতিটি ইনপুট নথিতে, $ অনুসন্ধানের পর্যায়ে একটি নতুন অ্যারে ক্ষেত্র যুক্ত করা হয়েছে যার উপাদানগুলি "যোগদান করেছেন" সংগ্রহের ম্যাচিং ডকুমেন্ট। $ দেখার পর্যায়টি এই পুনরায় আকারযুক্ত নথিগুলি পরবর্তী পর্যায়ে পাস করে। $ দেখার পর্যায়ে নিম্নলিখিত বাক্য গঠন রয়েছে:

সমতা ম্যাচ

ইনপুট ডকুমেন্টগুলি থেকে "যোগ দেওয়া" সংগ্রহের নথি থেকে একটি ক্ষেত্রের সাথে একটি ফিল্ডের মধ্যে সমতা ম্যাচটি সম্পাদন করতে, $ দেখার পর্যায়ে নিম্নলিখিত বাক্য গঠন রয়েছে:

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

ক্রিয়াকলাপটি নিম্নলিখিত সিউডো-এসকিউএল বিবৃতিটির সাথে সামঞ্জস্য করবে:

SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT <documents as determined from the pipeline>
                               FROM <collection to join>
                               WHERE <pipeline> );

মঙ্গো ইউআরএল


সাব-কোয়েরি যোগদানের চেয়ে সম্পূর্ণ আলাদা, যদি আপনার বাম দিকের টেবিলটি বিশাল হয় তবে সাব-কোয়েরির অর্থ প্রতিটি সারিতে একটি কোয়েরি নিজেই করতে হবে। এটা খুব ধীর হয়ে যাবে। স্কয়ারে যোগ দিন খুব দ্রুত।
yww325

8

আগে 3.2.6 , MongoDB সমর্থন মাইএসকিউএল মত ক্যোয়ারী যোগদানের নেই। সমাধানের নীচে যা আপনার পক্ষে কাজ করে।

 db.getCollection('comments').aggregate([
        {$match : {pid : 444}},
        {$lookup: {from: "users",localField: "uid",foreignField: "uid",as: "userData"}},
   ])


3

মঙ্গোডিবি যোগদানের অনুমতি দেয় না তবে আপনি এটি পরিচালনা করতে প্লাগইন ব্যবহার করতে পারেন। মঙ্গো-জয়েন প্লাগইনটি পরীক্ষা করুন। এটি সেরা এবং আমি ইতিমধ্যে এটি ব্যবহার করেছি। আপনি সরাসরি এনপিএম ব্যবহার করে এটি ইনস্টল করতে পারেন npm install mongo-join। আপনি উদাহরণ সহ পুরো ডকুমেন্টেশন চেক আউট করতে পারেন ।

(++) সত্যই সহায়ক সরঞ্জাম যখন আমাদের (এন) সংগ্রহগুলিতে যোগ দিতে হবে

(-) আমরা কোয়েরির শীর্ষ স্তরের শর্তগুলি প্রয়োগ করতে পারি

উদাহরণ

var Join = require('mongo-join').Join, mongodb = require('mongodb'), Db = mongodb.Db, Server = mongodb.Server;
db.open(function (err, Database) {
    Database.collection('Appoint', function (err, Appoints) {

        /* we can put conditions just on the top level */
        Appoints.find({_id_Doctor: id_doctor ,full_date :{ $gte: start_date },
            full_date :{ $lte: end_date }}, function (err, cursor) {
            var join = new Join(Database).on({
                field: '_id_Doctor', // <- field in Appoints document
                to: '_id',         // <- field in User doc. treated as ObjectID automatically.
                from: 'User'  // <- collection name for User doc
            }).on({
                field: '_id_Patient', // <- field in Appoints doc
                to: '_id',         // <- field in User doc. treated as ObjectID automatically.
                from: 'User'  // <- collection name for User doc
            })
            join.toArray(cursor, function (err, joinedDocs) {

                /* do what ever you want here */
                /* you can fetch the table and apply your own conditions */
                .....
                .....
                .....


                resp.status(200);
                resp.json({
                    "status": 200,
                    "message": "success",
                    "Appoints_Range": joinedDocs,


                });
                return resp;


            });

    });

2

একত্রিতকরণ পাইপলাইনটি ব্যবহার করে আপনি এটি করতে পারেন, তবে এটি নিজে লিখতে কষ্ট হচ্ছে।

আপনি mongo-join-queryআপনার কোয়েরি থেকে স্বয়ংক্রিয়ভাবে একত্রিত পাইপলাইন তৈরি করতে ব্যবহার করতে পারেন ।

আপনার ক্যোয়ারীটি এমন দেখাচ্ছে:

const mongoose = require("mongoose");
const joinQuery = require("mongo-join-query");

joinQuery(
    mongoose.models.Comment,
    {
        find: { pid:444 },
        populate: ["uid"]
    },
    (err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);

আপনার ফলাফলের uidক্ষেত্রে ক্ষেত্রটিতে ব্যবহারকারী অবজেক্ট থাকবে এবং আপনি যতগুলি গভীর স্তর চান তার সাথে লিংক করতে পারেন। আপনি ব্যবহারকারীর কাছে রেফারেন্স তৈরি করতে পারেন, যা একটি দলকে রেফারেন্স তৈরি করে, যা অন্য কোনও কিছুতে রেফারেন্স তৈরি করে makes

দাবি অস্বীকার : আমি mongo-join-queryএই সঠিক সমস্যার মোকাবিলা করার জন্য লিখেছি ।


0

প্লেঅর্ম এটি আপনার জন্য এস-এসকিউএল (স্কেলেবল এসকিউএল) ব্যবহার করে এটি করতে পারে যা কেবলমাত্র পার্টিশনের মধ্যেই যোগ করতে পারে এমন পার্টিশন যুক্ত করে।


-2

না, মনে হচ্ছে না আপনি এটি ভুল করছেন। মঙ্গোডিবি "ক্লায়েন্ট সাইড" এ যোগ দেয়। অনেক সুন্দর আপনি বলেছেন:

এই মুহুর্তে, আমি প্রথমে আমার মতামতগুলির সাথে মিলে যায় এমন মন্তব্যগুলি পেয়ে যাচ্ছি, তারপরে ফলাফলের সেটটিতে সমস্ত ইউডির সন্ধান করা, ব্যবহারকারীর জিনিসগুলি পাওয়া এবং মন্তব্যের ফলাফলের সাথে মার্জ করা। মনে হচ্ছে আমি এটি ভুল করছি।

1) Select from the collection you're interested in.
2) From that collection pull out ID's you need
3) Select from other collections
4) Decorate your original results.

এটি কোনও "আসল" যোগদান নয়, তবে এটি এসকিউএল যোগদানের চেয়ে আসলে অনেক বেশি কার্যকর কারণ আপনাকে মূলত নির্বাচিত সেটটি সাজানোর পরিবর্তে "অনেক" পক্ষের যোগদানের জন্য নকল সারিগুলি নিয়ে কাজ করতে হবে না।

এই পৃষ্ঠায় প্রচুর আজেবাজে কথা এবং FUD রয়েছে is 5 বছর পরে দেখা যাচ্ছে মঙ্গোডিবি এখনও একটি জিনিস।


"" অনেক "পক্ষের সাথে যোগ দেওয়ার জন্য আপনাকে নকল সারিগুলির সাথে ডিল করতে হবে না - আপনি এর দ্বারা কী বোঝেন তা ধারণা নেই। আপনি কি স্পষ্ট করতে পারেন?
মার্ক এমেরি

1
@ মার্কআমেরি, নিশ্চিত এসকিউএল-এ একটি এনএন সম্পর্ক নকল সারি ফিরবে। উদাহরণস্বরূপ বন্ধুরা। বব যদি মেরি এবং জেনের সাথে বন্ধুত্বপূর্ণ হয় তবে আপনি ববের জন্য 2 সারি পাবেন: বব, মেরি এবং বব, জেন। 2 ববস একটি মিথ্যা, শুধুমাত্র একটি বব আছে। ক্লায়েন্ট-পার্শ্বে যোগদানের সাথে আপনি ববকে দিয়ে শুরু করতে পারেন এবং কীভাবে পছন্দ করেন তা সজ্জিত করতে পারেন: বব, "মেরি এবং জেন"। এসকিউএল আপনাকে সাবকিউরিগুলি দিয়ে এটি করা যাক, তবে এটি ক্লায়েন্টের উপর করা যায় এমন ডিবি সার্ভারে কাজ করছে।
মাইকেল কোল

-3

আমি মনে করি, আপনার যদি সাধারণীকরণের ডেটা টেবিলগুলির প্রয়োজন হয় - আপনার আরও কিছু ডাটাবেস সমাধান চেষ্টা করা দরকার।

কিন্তু আমি উপর মোঙ্গো যে sollution foun থাকেন গীত উপায় দ্বারা, টিপে কোডে - এটা মুভির নাম রয়েছে কিন্তু Noi সিনেমা এর আইডি

সমস্যা

তারা অভিনীত সিনেমাগুলির একটি অ্যারে সহ আপনার অভিনেতাদের একটি সংগ্রহ রয়েছে।

আপনি প্রতিটি অভিনেতার অ্যারে দিয়ে মুভিগুলির সংগ্রহ তৈরি করতে চান।

কিছু নমুনা তথ্য

 db.actors.insert( { actor: "Richard Gere", movies: ['Pretty Woman', 'Runaway Bride', 'Chicago'] });
 db.actors.insert( { actor: "Julia Roberts", movies: ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'] });

সমাধান

আমাদের অভিনেতা নথিতে প্রতিটি মুভিটি লুপ করা এবং প্রতিটি মুভি পৃথকভাবে নির্গত করতে হবে।

এখানে ক্যাচ কমানোর পর্যায়ে রয়েছে। আমরা হ্রাস পর্ব থেকে কোনও অ্যারে নির্গত করতে পারি না, সুতরাং আমাদের ফিরে আসা "মান" নথির ভিতরে অবশ্যই একটি অভিনেতা অ্যারে তৈরি করতে হবে।

কোড
map = function() {
  for(var i in this.movies){
    key = { movie: this.movies[i] };
    value = { actors: [ this.actor ] };
    emit(key, value);
  }
}

reduce = function(key, values) {
  actor_list = { actors: [] };
  for(var i in values) {
    actor_list.actors = values[i].actors.concat(actor_list.actors);
  }
  return actor_list;
}

লক্ষ্য করুন কীভাবে অভিনেতা তালিকাভুক্ত আসলে একটি জাভাস্ক্রিপ্ট অবজেক্ট যা এতে একটি অ্যারে রয়েছে। এছাড়াও লক্ষ্য করুন যে মানচিত্রটি একই কাঠামোটি প্রকাশ করে।

মানচিত্রটি সম্পাদন / হ্রাস করতে নিম্নলিখিত চালান, এটিকে "পাইভট" সংগ্রহের আউটপুট করুন এবং ফলাফলটি মুদ্রণ করুন:

প্রিন্টজসন (db.actors.mapReduce (মানচিত্র, হ্রাস, "পিভট")); db.pivot.find () foreach (printjson)।

এখানে নমুনা আউটপুট দেওয়া আছে, নোট করুন যে "প্রেটি ওম্যান" এবং "রুনাও ব্রাইড" উভয়েই "রিচার্ড গেরি" এবং "জুলিয়া রবার্টস" রয়েছে।

{ "_id" : { "movie" : "Chicago" }, "value" : { "actors" : [ "Richard Gere" ] } }
{ "_id" : { "movie" : "Erin Brockovich" }, "value" : { "actors" : [ "Julia Roberts" ] } }
{ "_id" : { "movie" : "Pretty Woman" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }
{ "_id" : { "movie" : "Runaway Bride" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }


নোট করুন যে এই উত্তরের বেশিরভাগ সামগ্রী (যেমন বোঝার মতো ইংরেজিতে বিটটি রয়েছে) উত্তরদাতাদের দেওয়া গিটহাব লিঙ্কে মঙ্গোডিবি কুকবুক থেকে অনুলিপি করা হয়েছে।
মার্ক অ্যামেরি

-4

আমরা মঙ্গোডিবি সাব কোয়েরি ব্যবহার করে দুটি সংগ্রহকে মার্জ করতে পারি। এখানে উদাহরণস্বরূপ, মন্তব্যগুলি -

`db.commentss.insert([
  { uid:12345, pid:444, comment:"blah" },
  { uid:12345, pid:888, comment:"asdf" },
  { uid:99999, pid:444, comment:"qwer" }])`

Userss--

db.userss.insert([
  { uid:12345, name:"john" },
  { uid:99999, name:"mia"  }])

JOIN- এর জন্য মঙ্গোডিবির সাব কোয়েরি

`db.commentss.find().forEach(
    function (newComments) {
        newComments.userss = db.userss.find( { "uid": newComments.uid } ).toArray();
        db.newCommentUsers.insert(newComments);
    }
);`

সদ্য উত্পন্ন সংগ্রহ থেকে ফলাফল পান -

db.newCommentUsers.find().pretty()

ফলাফল--

`{
    "_id" : ObjectId("5511236e29709afa03f226ef"),
    "uid" : 12345,
    "pid" : 444,
    "comment" : "blah",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f0"),
    "uid" : 12345,
    "pid" : 888,
    "comment" : "asdf",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f1"),
    "uid" : 99999,
    "pid" : 444,
    "comment" : "qwer",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f3"),
            "uid" : 99999,
            "name" : "mia"
        }
    ]
}`

আশা করি এটি সাহায্য করবে।


7
আপনি কেন এই প্রায় এক বছরের পুরানো উত্তরটি মূলত অনুলিপি করলেন? stackoverflow.com/a/22739813/4186945
hackel
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.