MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Menautkan &Membuat Gabungan MongoDB Menggunakan SQL:Bagian 3

Beberapa GABUNG dalam satu kueri

Multiple JOIN biasanya diasosiasikan dengan beberapa koleksi, tetapi Anda harus memiliki pemahaman dasar tentang cara kerja INNER JOIN (lihat posting saya sebelumnya tentang topik ini). Selain dua koleksi yang kami miliki sebelumnya; unit dan siswa, mari tambahkan koleksi ketiga dan beri label olahraga. Isi koleksi olahraga dengan data di bawah ini:

{
    "_id" : 1,"tournamentsPlayed" : 6,
    "gamesParticipated" : [{"hockey" : "midfielder","football" : "stricker","handball" : "goalkeeper"}],
    "sportPlaces" : ["Stafford Bridge","South Africa", "Rio Brazil"]
}
{
    "_id" : 2,"tournamentsPlayed" : 3,
    "gamesParticipated" : [{"hockey" : "goalkeeper","football" : "stricker", "handball" : "midfielder"}],
    "sportPlaces" : ["Ukraine","India", "Argentina"]
}
{
    "_id" : 3,"tournamentsPlayed" : 10,
    "gamesParticipated" : [{"hockey" : "stricker","football" : "goalkeeper","tabletennis" : "doublePlayer"}],
    "sportPlaces" : ["China","Korea","France"]
}

Kami ingin, misalnya, mengembalikan semua data untuk siswa dengan nilai bidang _id sama dengan 1. Biasanya, kami akan menulis kueri untuk mengambil nilai bidang _id dari koleksi siswa, kemudian menggunakan nilai yang dikembalikan untuk kueri data dalam dua koleksi lainnya. Akibatnya, ini tidak akan menjadi pilihan terbaik terutama jika sejumlah besar dokumen terlibat. Pendekatan yang lebih baik adalah dengan menggunakan fitur SQL program Studio3T. Kita dapat mengkueri MongoDB kita dengan konsep SQL normal dan kemudian mencoba untuk menyetel kasar kode shell Mongo yang dihasilkan agar sesuai dengan spesifikasi kita. Misalnya, mari kita ambil semua data dengan _id sama dengan 1 dari semua koleksi:

SELECT  *
  FROM students
    INNER JOIN units
      ON students._id = units._id
    INNER JOIN sports
      ON students._id = sports._id
  WHERE students._id = 1;

Dokumen yang dihasilkan akan menjadi:

{ 
    "students" : {"_id" : NumberInt(1),"name" : "James Washington","age" : 15.0,"grade" : "A","score" : 10.5}, 
    "units" : {"_id" : NumberInt(1),"grades" : {Maths" : "A","English" : "A","Science" : "A","History" : "B"}
    }, 
    "sports" : {
        "_id" : NumberInt(1),"tournamentsPlayed" : NumberInt(6), 
        "gamesParticipated" : [{"hockey" : "midfielder", "football" : "striker","handball" : "goalkeeper"}], 
        "sportPlaces" : ["Stafford Bridge","South Africa","Rio Brazil"]
    }
}

Dari tab Kode kueri, kode MongoDB koresponden akan menjadi:

db.getCollection("students").aggregate(
    [{ "$project" : {"_id" : NumberInt(0),"students" : "$$ROOT"}}, 
        { "$lookup" : {"localField" : "students._id","from" : "units","foreignField" : "_id", "as" : "units"}}, 
        { "$unwind" : {"path" : "$units","preserveNullAndEmptyArrays" : false}}, 
        { "$lookup" : {"localField" : "students._id","from" : "sports", "foreignField" : "_id","as" : "sports"}}, 
        { "$unwind" : {"path" : "$sports", "preserveNullAndEmptyArrays" : false}}, 
        { "$match" : {"students._id" : NumberLong(1)}}
    ]
);

Melihat ke dalam dokumen yang dikembalikan, secara pribadi saya tidak terlalu senang dengan struktur data terutama dengan dokumen yang disematkan. Seperti yang Anda lihat, ada bidang _id yang dikembalikan dan untuk unit kami mungkin tidak memerlukan bidang nilai untuk disematkan di dalam unit.

Kami ingin memiliki bidang unit dengan unit yang disematkan dan bukan bidang lainnya. Ini membawa kita ke bagian nada kasar. Seperti pada postingan sebelumnya, salin kode menggunakan ikon salin yang disediakan dan masuk ke panel agregasi, rekatkan isinya menggunakan ikon tempel.

Hal pertama yang pertama, operator $match harus menjadi tahap pertama, jadi pindahkan ke posisi pertama dan dapatkan sesuatu seperti ini:

Klik tab tahap pertama dan ubah kueri menjadi:

{
    "_id" : NumberLong(1)
}

Kami kemudian perlu memodifikasi kueri lebih lanjut untuk menghapus banyak tahapan penyematan data kami. Untuk melakukannya, kami menambahkan bidang baru untuk mengambil data untuk bidang yang ingin kami hilangkan yaitu:

db.getCollection("students").aggregate(
    [
        { "$project" : { "_id" : NumberInt(0), "students" : "$$ROOT"}}, 
        { "$match" : {"students._id" : NumberLong(1)}}, 
        { "$lookup" : { "localField" : "students._id", "from" : "units","foreignField" : "_id", "as" : "units"}}, 
        { "$addFields" : { "_id": "$students._id","units" : "$units.grades"}}, 
        { "$unwind" : { "path" : "$units",  "preserveNullAndEmptyArrays" : false}}, 
        { "$lookup" : {"localField" : "students._id", "from" : "sports", "foreignField" : "_id", "as" : "sports"}}, 
        { "$unwind" : { "path" : "$sports","preserveNullAndEmptyArrays" : false}}, 
        { "$project" : {"sports._id" : 0.0}}
        ]
);

Seperti yang Anda lihat, dalam proses fine tuning kami telah memperkenalkan unit bidang baru yang akan menimpa konten dari pipa agregasi sebelumnya dengan nilai sebagai bidang yang disematkan. Selanjutnya, kami telah membuat bidang _id untuk menunjukkan bahwa data tersebut terkait dengan dokumen apa pun dalam koleksi dengan nilai yang sama. Tahap $project terakhir adalah menghapus field _id di dokumen olahraga sehingga kita dapat memiliki data yang disajikan dengan rapi seperti di bawah ini.

{  "_id" : NumberInt(1), 
    "students" : {"name" : "James Washington", "age" : 15.0,  "grade" : "A", "score" : 10.5}, 
    "units" : {"Maths" : "A","English" : "A", "Science" : "A","History" : "B"}, 
    "sports" : {
        "tournamentsPlayed" : NumberInt(6), 
        "gamesParticipated" : [{"hockey" : "midfielder","football" : "striker","handball" : "goalkeeper"}],  
        "sportPlaces" : ["Stafford Bridge", "South Africa", "Rio Brazil"]
        }
}

Kami juga dapat membatasi bidang mana yang harus dikembalikan dari sudut pandang SQL. Misalnya kita dapat mengembalikan nama siswa, unit yang dikerjakan siswa ini dan jumlah turnamen yang dimainkan menggunakan beberapa GABUNG dengan kode di bawah ini:

SELECT  students.name, units.grades, sports.tournamentsPlayed
  FROM students
    INNER JOIN units
      ON students._id = units._id
    INNER JOIN sports
      ON students._id = sports._id
  WHERE students._id = 1;

Ini tidak memberi kita hasil yang paling tepat. Jadi seperti biasa, salin dan tempel di panel agregasi. Kami menyempurnakan kode di bawah ini untuk mendapatkan hasil yang sesuai.

db.getCollection("students").aggregate(
    [
        { "$project" : { "_id" : NumberInt(0), "students" : "$$ROOT"}}, 
        { "$match" : {"students._id" : NumberLong(1)}}, 
        { "$lookup" : { "localField" : "students._id", "from" : "units","foreignField" : "_id", "as" : "units"}}, 
        { "$addFields" : {"units" : "$units.grades"}}, 
        { "$unwind" : { "path" : "$units",  "preserveNullAndEmptyArrays" : false}}, 
        { "$lookup" : {"localField" : "students._id", "from" : "sports", "foreignField" : "_id", "as" : "sports"}}, 
        { "$unwind" : { "path" : "$sports","preserveNullAndEmptyArrays" : false}}, 
        { "$project" : {"name" : "$students.name", "grades" : "$units.grades", "tournamentsPlayed" : "$sports.tournamentsPlayed"}
        }}
        ]
);

Hasil agregasi dari konsep SQL JOIN ini memberi kita struktur data yang rapi dan rapi seperti yang ditunjukkan di bawah ini.

{ 
    "name" : "James Washington", 
    "grades" : {"Maths" : "A", "English" : "A", "Science" : "A", "History" : "B"}, 
    "tournamentsPlayed" : NumberInt(6)
}

Cukup sederhana, bukan? Datanya cukup rapi seolah-olah disimpan dalam satu koleksi sebagai satu dokumen.

KIRI LUAR GABUNG

LEFT OUTER JOIN biasanya digunakan untuk menunjukkan dokumen yang tidak sesuai dengan hubungan yang paling banyak digambarkan. Kumpulan hasil gabungan LEFT OUTER berisi semua baris dari kedua koleksi yang memenuhi kriteria klausa WHERE, sama dengan kumpulan hasil INNER JOIN. Selain itu, dokumen dari koleksi kiri yang tidak memiliki dokumen yang cocok di koleksi kanan juga akan dimasukkan ke dalam kumpulan hasil. Bidang yang dipilih dari tabel sisi kanan akan mengembalikan nilai NULL. Namun, dokumen apa pun dalam koleksi kanan, yang tidak memiliki kriteria yang cocok dengan koleksi kiri, tidak akan dikembalikan.

Lihat dua koleksi ini:

siswa

{"_id" : 1,"name" : "James Washington","age" : 15.0,"grade" : "A","score" : 10.5}
{"_id" : 2,"name" : "Clinton Ariango","age" : 14.0,"grade" : "B","score" : 7.5}
{"_id" : 4,"name" : "Mary Muthoni","age" : 16.0,"grade" : "A","score" : 11.5}

Satuan

{"_id" : 1,"Maths" : "A","English" : "A","Science" : "A","History" : "B"}
{"_id" : 2,"Maths" : "B","English" : "B","Science" : "A","History" : "B"}
{"_id" : 3,"Maths" : "A","English" : "A","Science" : "A","History" : "A"}

Dalam koleksi siswa kami tidak memiliki nilai bidang _id yang disetel ke 3 tetapi dalam koleksi unit yang kami miliki. Demikian juga, tidak ada nilai bidang _id 4 di dalam kumpulan unit. Jika kami menggunakan koleksi siswa sebagai opsi kiri kami dalam pendekatan GABUNG dengan kueri di bawah ini:

SELECT *
  FROM students
    LEFT OUTER JOIN units
      ON students._id = units._id

Dengan kode ini kita akan mendapatkan hasil sebagai berikut:

{
    "students" : {"_id" : 1,"name" : "James Washington","age" : 15,"grade" : "A","score" : 10.5},
    "units" : {"_id" : 1,"grades" : {"Maths" : "A","English" : "A", "Science" : "A","History" : "B"}}
}
{
    "students" : {"_id" : 2,"name" : "Clinton Ariango", "age" : 14,"grade" : "B", "score" : 7.5 }
}
{
    "students" : {"_id" : 3,"name" : "Mary Muthoni","age" : 16,"grade" : "A","score" : 11.5},
    "units" : {"_id" : 3,"grades" : {"Maths" : "A","English" : "A","Science" : "A","History" : "A"}}
}

Dokumen kedua tidak memiliki bidang unit karena tidak ada dokumen yang cocok dalam koleksi unit. Untuk kueri SQL ini, Kode Mongo koresponden akan menjadi

db.getCollection("students").aggregate(
    [
        { 
            "$project" : {"_id" : NumberInt(0), "students" : "$$ROOT"}}, 
        { 
            "$lookup" : {"localField" : "students._id",  "from" : "units", "foreignField" : "_id", "as" : "units"}
        }, 
        { 
            "$unwind" : { "path" : "$units", "preserveNullAndEmptyArrays" : true}
        }
    ]
);

Tentu saja kami telah belajar tentang fine-tuning, sehingga Anda dapat melanjutkan dan merestrukturisasi alur agregasi agar sesuai dengan hasil akhir yang Anda inginkan. SQL adalah alat yang sangat kuat sejauh menyangkut manajemen basis data. Ini adalah subjek yang luas, Anda juga dapat mencoba menggunakan klausa IN dan GROUP BY untuk mendapatkan kode koresponden untuk MongoDB dan melihat cara kerjanya.

Kesimpulan

Membiasakan diri dengan teknologi (basis data) baru selain yang biasa Anda gunakan dapat memakan banyak waktu. Database relasional masih lebih umum daripada yang non-relasional. Namun demikian, dengan diperkenalkannya MongoDB, banyak hal telah berubah dan orang-orang ingin mempelajarinya secepat mungkin karena kinerjanya yang kuat.

Mempelajari MongoDB dari awal bisa sedikit membosankan, tetapi kita dapat menggunakan pengetahuan SQL untuk memanipulasi data di MongoDB, mendapatkan kode MongoDB relatif dan menyempurnakannya untuk mendapatkan hasil yang paling sesuai. Salah satu alat yang tersedia untuk menyempurnakan ini adalah Studio 3T. Ia menawarkan dua fitur penting yang memfasilitasi pengoperasian data yang kompleks, yaitu:fitur query SQL dan editor Agregasi. Penyesuaian kueri yang tepat tidak hanya akan memastikan Anda mendapatkan hasil terbaik, tetapi juga meningkatkan kinerja dalam hal penghematan waktu.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. jenis kustom luwak/mongodb

  2. MongoDB $asinh

  3. Tambahkan data ke file gridfs yang ada

  4. Di mana posisi mongodb dalam teorema CAP?

  5. MongoDB $log