Tugas pengelompokan MongoDB - beberapa grup, ketentuan

Tujuan saya adalah mendapatkan semua dokumen 'siswa' milik 'kelas' yang memiliki setidaknya satu siswa kelas "biru" dan setidaknya satu kelas "merah".

Saya cenderung melakukan serangkaian pertanyaan dengan Python (pymongo), menangani tugas secara langsung.

Saya ingin tahu apakah ada saluran agregasi cerdas yang dapat saya gunakan!

Diberikan:

Koleksi kelas:

{ class_id: 'a' }
{ class_id: 'b' }

Koleksi Siswa:

{ class_id: 'a',
grade: 'blue' }

{class_id: 'a',
grade: 'red' }

person Tony Sepia    schedule 26.12.2016    source sumber


Jawaban (1)


Anda dapat menggunakan:

  • a $group untuk mengelompokkan berdasarkan class_id dan $push semua nilai dalam array sehingga kita dapat dengan mudah menyimpulkan pada langkah berikutnya kelas mana yang "berisi" blue. Pertahankan dokumen saat ini dengan $$ROOT karena kita memerlukannya siswa yang cocok dengan class_id

  • a $match untuk mencocokkan hanya kelas yang memiliki nilai blue di dalamnya

  • sebuah $unwind untuk menghapus array siswa yang dihasilkan oleh $$ROOT sebelumnya

  • a $project untuk mengatur ulang dokumen Anda dengan baik

Kuerinya adalah:

db.students.aggregate([{
    "$group": {
        "_id": "$class_id",
        "grades": { "$push": "$grade" },
        "students": { "$push": "$$ROOT" }
    }
}, {
    "$match": {
        "grades": { "$all": ["blue","red"] }
    }
}, {
    "$unwind": "$students"
}, {
    "$project": {
        "_id": "$students._id",
        "class_id": "$students.class_id",
        "grade": "$students.grade",
    }
}])

Jika Anda perlu mencocokkan warna selain ["biru","merah"] Anda dapat menambahkan lebih banyak di agregasi $match ($in: ["blue","red","yellow"])

Untuk mengimplementasikannya di PyMongo, caranya sangat mudah:

from pymongo import MongoClient
import pprint

db = MongoClient().testDB

pipeline = [ <the_aggregation_query_here> ]

pprint.pprint(list(db.students.aggregate(pipeline)))

Selain itu, untuk mencocokkan hanya siswa yang termasuk dalam koleksi classes, lakukan $lookup dan cocokkan dengan yang tidak kosong. Tambahkan yang berikut ini pada kueri agregasi:

{
    $lookup: {
        from: "classes",
        localField: "class_id",
        foreignField: "class_id",
        as: "class"
    }
}, {
    $match: {
        "class": { $not: { $size: 0 } }
    }
}
person Bertrand Martel    schedule 26.12.2016