Hướng dẫn nested group mongodb - nhóm lồng nhau mongodb

Context:

I have a MongoDB full of Documents like this, which I want to dumb into one grouped json:

[
  {
    "_id": "615dc97907f597330c510279",
    "code": "SDFSDFSDF",
    "location": "ABC1",
    "week_number": 40,
    "year": 2021,
    "region": "NA"
  },

  ....

  {
    "_id": "615dc97907f597330c51027a",
    "code": "SDFSGSGR",
    "location": "ABC1",
    "week_number": 40,
    "year": 2021,
    "region": "EU"
  },

  ....

  {
    "_id": "615dc97607f597330c50ff50",
    "code": "GGSFHSFS",
    "location": "DEF2",
    "week_number": 40,
    "year": 2021,
    "region": "EU",
    "audit_result": {
      "issues_found": true,
      "comment": "comment."
    }
  }
]

I am trying to write an aggregation which should return and object like this:

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}

Problem:

I am not 100% sure how.

I started grouping them by region but I am not sure how to proceed after the first group. I tried grouping them by location first and group my way up to region but that also does not seem to work as I expected it.

The docs don't talk about a case like this and examples I find only group by one or two things, not four.

any insights highly appreciated :)

Tài liệu về nhà → Hướng dẫn sử dụng MongoDB → MongoDB ManualMongoDB Manual


Sử dụng menu chọn ngôn ngữ của bạn ở phía trên bên phải để đặt ngôn ngữ của các ví dụ sau.Select your language drop-down menu in the upper-right to set the language of the following examples.Select your language drop-down menu in the upper-right to set the language of the following examples.


Ví dụ: truy vấn sau chọn tất cả các tài liệu trong đó trường

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
8 bằng tài liệu
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
9:

Bình đẳng khớp với toàn bộ tài liệu nhúng yêu cầu một kết hợp chính xác của tài liệu

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
0 được chỉ định, bao gồm cả thứ tự trường. Ví dụ: truy vấn sau không khớp với bất kỳ tài liệu nào trong bộ sưu tập
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
1:

Để chỉ định một điều kiện truy vấn trên các trường trong tài liệu nhúng/lồng nhau, hãy sử dụng ký hiệu DOT (____10).

Ghi chú

Khi truy vấn sử dụng ký hiệu DOT, trường và trường lồng nhau phải ở bên trong dấu ngoặc kép.

Ví dụ sau chọn tất cả các tài liệu trong đó trường

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
1 lồng nhau trong trường
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
8 bằng
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3:

Truy vấn sau sử dụng ít hơn toán tử (

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
4) trên trường
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
5 được nhúng trong trường
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
8:

Truy vấn sau chọn tất cả các tài liệu trong đó trường lồng nhau

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
5 nhỏ hơn
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
8, trường lồng nhau
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
1 bằng
//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
3 và trường
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
01 bằng
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
02:

Để biết các ví dụ truy vấn bổ sung, xem:

  • Tài liệu truy vấn

  • Truy vấn một mảng

  • Truy vấn một loạt các tài liệu nhúng

1. Embedded Documents là gì?

Embedded documents (Tài liệu nhúng) là documents có lược đồ riêng và là 1 phần của documents khác. Hiểu đơn giản thì embedded documents là 1 field nằm trong 1 collection thay vì lưu dữ liệu kiểu References ta phải thiết kế 2 collection để thể hiện mối quan hệ One-to-Many.

Embedded documents có mọi đặc điểm như 1 model, ta có thể sử dụng validators, middleware,... để xử lý lỗi khi làm việc với kiểu dữ liệu này.

Trong Mongoose, Embedded documents được khai báo dưới dạng array trong collection chứa nó và như nói phía trên, nó sẽ có 1 lược đồ riêng nhưng nằm trong cùng 1 file với collection chính.

Ví dụ: Ta cần quản lý các Students và mỗi students sẽ có nhiều Projects khác nhau. Khi này ta sẽ có 1 file chứa lược đồ như sau: Ta cần quản lý các Students và mỗi students sẽ có nhiều Projects khác nhau. Khi này ta sẽ có 1 file chứa lược đồ như sau: Ta cần quản lý các Students và mỗi students sẽ có nhiều Projects khác nhau. Khi này ta sẽ có 1 file chứa lược đồ như sau:

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
2

Ta có thể thấy cặp key-value projects: [Projects] trong lược đồ Student, value là 1 array đặc biệt có các phương thức cụ thể để làm việc với Embedded Documents và array này là một thể hiện của DocumentArray. Ở các cặp key-value khác thì value là 1 kiểu dữ liệu được định nghĩa sẵn. Ta cần định nghĩa cho DocumentArray này bằng 1 lược đồ riêng.projects: [Projects] trong lược đồ Student, value là 1 array đặc biệt có các phương thức cụ thể để làm việc với Embedded Documents và array này là một thể hiện của DocumentArray. Ở các cặp key-value khác thì value là 1 kiểu dữ liệu được định nghĩa sẵn. Ta cần định nghĩa cho DocumentArray này bằng 1 lược đồ riêng.projects: [Projects] trong lược đồ Student, value là 1 array đặc biệt có các phương thức cụ thể để làm việc với Embedded Documents và array này là một thể hiện của DocumentArray. Ở các cặp key-value khác thì value là 1 kiểu dữ liệu được định nghĩa sẵn. Ta cần định nghĩa cho DocumentArray này bằng 1 lược đồ riêng.

Lưu ý: Lược đồ con luôn phải được xác định trước lược đồ chính.: Lược đồ con luôn phải được xác định trước lược đồ chính.: Lược đồ con luôn phải được xác định trước lược đồ chính.

2. So sánh Embedded Documents vs References

Trước khi so sánh giữa 2 kiểu mô hình dữ liệu thì ta xem qua với ví dụ phía trên khi sử dụng kiểu References thì xây dựng lược đồ như thế nào đã nhé.References thì xây dựng lược đồ như thế nào đã nhé.References thì xây dựng lược đồ như thế nào đã nhé.

Ta có 2 file: Project.js và Student.js

//Project.js
var Project = new Schema({
  title: String,
  unit: String,
  student: { type:Schema.ObjectId, ref: "Student" }
});

mongoose.model('Project', Project);
{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
0

References lưu trữ các mối quan hệ giữa dữ liệu bằng cách link từ collection này sang collection khác (tạo tham chiếu đến thằng cha) thông qua ObjectIds. Ở đây, nếu ta có một bản dữ liệu trong từng Student thì ta lưu ObjectID của Student trên từng Project. Thuộc tính ref phải khớp chính xác với tên model trong định nghĩa model của chúng ta.

Cơ bản thì cách sử dụng 2 mô hình dữ liệu này trong Mongoose là như vậy. Mỗi kiểu có ưu, nhược điểm khác nhau:

Embedded DocumentsReferences
Ưu điểm - Truy vấn và cập nhật dữ liệu dễ dàng.- Đạt hiệu suất cao trong việc đọc dữ liệu - Đạt hiệu suất cao trong việc đọc dữ liệu
- Đạt hiệu suất cao trong việc đọc dữ liệu
- Có thể cung cấp linh hoạt hơn với truy vấn. - Đạt hiệu suất cao trong việc ghi dữ liệu- Đạt hiệu suất cao trong việc ghi dữ liệu
- Đạt hiệu suất cao trong việc ghi dữ liệu
Nhược điểm - Kích thước document lớn ảnh hưởng đến việc ghi dữ liệu vì mỗi document không thể vượt quá 16MB - Với các hệ thống có nhiều collections thì truy vấn sẽ khó khăn hơn, yêu cầu nhiều công việc hơn

Bài viết này nói về Embedded Document nên chúng ta sẽ tiếp tục với các thao tác cơ bản của mô hình dữ liệu này.Embedded Document nên chúng ta sẽ tiếp tục với các thao tác cơ bản của mô hình dữ liệu này.Embedded Document nên chúng ta sẽ tiếp tục với các thao tác cơ bản của mô hình dữ liệu này.

3. Thêm 1 Embedded Document vào 1 mảng

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
5

4. Xóa 1 Embedded Document

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
6

5. Tìm Embedded Document theo id

DocumentArrays có method đặc biệt là id() để lọc các Embedded Document theo thuộc tính _id của chúngid() để lọc các Embedded Document theo thuộc tính _id của chúngid() để lọc các Embedded Document theo thuộc tính _id của chúng

{
  [
    "EU": {
      2021: {
        40: {
          "ABC1": {
            (All documents for location ABC1 and week 40, year 2021 and region EU)
          }
        },
        39: {
          ....
        }
      },
      2020: {
        ....
      }
    },
    "NA": {
      ....
    }
  ]
}
7

Bài viết đến đây kết thúc rồi!!! Mình xin cảm ơn các bạn đã đọc bài. Nếu có sai sót hoặc cách diễn đạt của mình sai thì hãy comment phía dưới nhé.

Tài liệu tham khảo:

  1. https://mongoosejs.com/docs/2.7.x/docs/embedded-documents.html
  2. https://docs.mongodb.com/manual/core/data-modeling-introduction/