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

Agregasi Mgo:bagaimana cara menggunakan kembali tipe model untuk kueri dan menghapus hasil campuran?

Kueri di atas mengembalikan dokumen yang "hampir" cocok dengan User dokumen, tetapi mereka juga memiliki posting masing-masing pengguna. Jadi pada dasarnya hasilnya adalah serangkaian User dokumen dengan Post larik atau irisan tertanam .

Salah satu caranya adalah dengan menambahkan Posts []*Post bidang ke User sendiri, dan kita akan selesai:

type User struct {
    ID         string    `bson:"_id"`
    Name       string    `bson:"name"`
    Registered time.Time `bson:"registered"`
    Posts      []*Post   `bson:"posts,omitempty"`
}

Saat ini berfungsi, tampaknya "berlebihan" untuk memperluas User dengan Post hanya demi satu permintaan. Jika kami melanjutkan jalan ini, User our type akan membengkak dengan banyak bidang "ekstra" untuk kueri yang berbeda. Belum lagi jika kita mengisi Posts dan simpan pengguna, posting tersebut akan disimpan di dalam User dokumen. Bukan yang kita inginkan.

Cara lain adalah dengan membuat UserWithPosts ketik menyalin User , dan menambahkan Posts []*Post bidang. Tak perlu dikatakan ini jelek dan tidak fleksibel (perubahan apa pun yang dilakukan pada User harus dicerminkan ke UserWithPosts secara manual).

Dengan Penyematan Struktur

Alih-alih memodifikasi User asli , dan alih-alih membuat UserWithPosts baru ketik dari "scratch", kita dapat menggunakan penyematan struct (menggunakan kembali User yang ada dan Post jenis) dengan sedikit trik:

type UserWithPosts struct {
    User  `bson:",inline"`
    Posts []*Post `bson:"posts"`
}

Perhatikan bson nilai tag ",inline" . Ini didokumentasikan di bson.Marshal() dan bson.Unmarshal() (kami akan menggunakannya untuk unmarshaling):

Dengan menggunakan penyematan dan ",inline" nilai tag, UserWithPosts type itu sendiri akan menjadi target yang valid untuk membongkar User dokumen, dan Post []*Post its bidang akan menjadi pilihan yang sempurna untuk "posts" yang dicari .

Menggunakannya:

var uwp *UserWithPosts
it := pipe.Iter()
for it.Next(&uwp) {
    // Use uwp:
    fmt.Println(uwp)
}
// Handle it.Err()

Atau mendapatkan semua hasil dalam satu langkah:

var uwps []*UserWithPosts
err := pipe.All(&uwps)
// Handle error

Deklarasi jenis UserWithPosts mungkin atau mungkin bukan deklarasi lokal. Jika Anda tidak membutuhkannya di tempat lain, itu bisa berupa deklarasi lokal dalam fungsi tempat Anda menjalankan dan memproses kueri agregasi, sehingga tidak akan menggembungkan jenis dan deklarasi yang ada. Jika Anda ingin menggunakannya kembali, Anda dapat mendeklarasikannya di tingkat paket (diekspor atau tidak diekspor), dan menggunakannya di mana pun Anda membutuhkannya.

Memodifikasi agregasi

Opsi lainnya adalah menggunakan $replaceRoot MongoDB untuk "mengatur ulang" dokumen hasil, sehingga struktur "sederhana" akan menutupi dokumen dengan sempurna:

// Query users with their posts:
pipe := collUsers.Pipe([]bson.M{
    {
        "$lookup": bson.M{
            "from":         "posts",
            "localField":   "_id",
            "foreignField": "userID",
            "as":           "posts",
        },
    },
    {
        "$replaceRoot": bson.M{
            "newRoot": bson.M{
                "user":  "$$ROOT",
                "posts": "$posts",
            },
        },
    },
})

Dengan pemetaan ulang ini, dokumen hasil dapat dimodelkan seperti ini:

type UserWithPosts struct {
    User  *User   `bson:"user"`
    Posts []*Post `bson:"posts"`
}

Perhatikan bahwa saat ini berfungsi, posts bidang semua dokumen akan diambil dari server dua kali:sekali sebagai posts bidang dokumen yang dikembalikan, dan sekali sebagai bidang user; kami tidak memetakan / menggunakannya tetapi ada di dokumen hasil. Jadi jika solusi ini dipilih, user.posts bidang harus dihapus mis. dengan $project panggung:

pipe := collUsers.Pipe([]bson.M{
    {
        "$lookup": bson.M{
            "from":         "posts",
            "localField":   "_id",
            "foreignField": "userID",
            "as":           "posts",
        },
    },
    {
        "$replaceRoot": bson.M{
            "newRoot": bson.M{
                "user":  "$$ROOT",
                "posts": "$posts",
            },
        },
    },
    {"$project": bson.M{"user.posts": 0}},
})



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. bagaimana saya bisa memvalidasi kata sandi nama pengguna untuk otentikasi mongodb melalui pymongo?

  2. Bersihkan input pengguna di Mongoose

  3. Bagaimana saya bisa menemukan dokumen Mongoid yang disematkan berdasarkan beberapa kriteria?

  4. Menghapus objek Javascript besar saat proses kehabisan memori

  5. Cara merepresentasikan array dengan tipe campuran