MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Tổng hợp Mgo:làm thế nào để sử dụng lại các loại mô hình để truy vấn và bỏ quản lý các kết quả hỗn hợp?

Truy vấn ở trên trả về các tài liệu "gần như" khớp với User tài liệu, nhưng chúng cũng có bài đăng của từng người dùng. Vì vậy, về cơ bản kết quả là một loạt User tài liệu có Post mảng hoặc lát nhúng .

Một cách là thêm Posts []*Post vào trường User chính nó, và chúng tôi sẽ hoàn thành:

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

Trong khi điều này hoạt động, có vẻ như "quá mức cần thiết" để mở rộng User với Posts chỉ vì lợi ích của một truy vấn duy nhất. Nếu chúng tôi tiếp tục con đường này, User của chúng tôi loại sẽ trở nên cồng kềnh với rất nhiều trường "bổ sung" cho các truy vấn khác nhau. Chưa kể nếu chúng tôi điền vào Posts và lưu người dùng, những bài đăng đó cuối cùng sẽ được lưu bên trong User tài liệu. Không phải những gì chúng tôi muốn.

Một cách khác là tạo UserWithPosts gõ sao chép User và thêm một Posts []*Post đồng ruộng. Không cần phải nói điều này xấu và không linh hoạt (bất kỳ thay đổi nào được thực hiện đối với User sẽ phải được phản ánh tới UserWithPosts thủ công).

Với tính năng Nhúng cấu trúc

Thay vì sửa đổi User ban đầu và thay vì tạo UserWithPosts mới nhập từ "đầu", chúng tôi có thể sử dụng nhúng cấu trúc (sử dụng lại User hiện có và Post loại) với một thủ thuật nhỏ:

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

Lưu ý giá trị thẻ bson ",inline" . Điều này được ghi lại tại bson.Marshal() bson.Unmarshal() (chúng tôi sẽ sử dụng nó để giải nén):

Bằng cách sử dụng tính năng nhúng và ",inline" giá trị thẻ, UserWithPosts loại chính nó sẽ là một mục tiêu hợp lệ để giải nén User tài liệu và Post []*Post của nó trường sẽ là một lựa chọn hoàn hảo cho "posts" đã tra cứu .

Sử dụng nó:

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

Hoặc nhận tất cả kết quả trong một bước:

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

Khai báo kiểu của UserWithPosts có thể là một khai báo cục bộ hoặc không. Nếu bạn không cần nó ở nơi khác, nó có thể là một khai báo cục bộ trong hàm nơi bạn thực thi và xử lý truy vấn tổng hợp, vì vậy nó sẽ không làm cồng kềnh các kiểu và khai báo hiện có của bạn. Nếu bạn muốn sử dụng lại nó, bạn có thể khai báo nó ở cấp độ gói (đã xuất hoặc chưa báo cáo) và sử dụng nó ở bất cứ đâu bạn cần.

Sửa đổi tổng hợp

Một tùy chọn khác là sử dụng $replaceRoot của MongoDB để "sắp xếp lại" các tài liệu kết quả, vì vậy cấu trúc "đơn giản" sẽ bao phủ hoàn hảo các tài liệu:

// 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",
            },
        },
    },
})

Với ánh xạ lại này, các tài liệu kết quả có thể được mô hình hóa như thế này:

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

Lưu ý rằng trong khi điều này hoạt động, posts trường của tất cả các tài liệu sẽ được tìm nạp từ máy chủ hai lần:một lần khi posts trường của các tài liệu được trả lại và từng là trường của user; chúng tôi không ánh xạ / sử dụng nó nhưng nó có trong các tài liệu kết quả. Vì vậy, nếu giải pháp này được chọn, user.posts trường nên được loại bỏ, ví dụ:với $project giai đoạn:

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. Mã hóa cơ sở dữ liệu MongoDB

  2. Tại sao trình điều khiển nút MongoDB tạo hồ sơ cá thể bị lỗi bị phá hủy?

  3. Toán tử $ arrayElemAt trong tổng hợp với Mongo <3.2

  4. Chỉ hiển thị các trường phù hợp cho tìm kiếm văn bản MongoDB

  5. Python + MongoDB - Lặp lại con trỏ quá chậm