Tổng hợp mongodb

Như chúng ta đã biết, việc sử dụng Aggregation trong mongoDb để thực hiện xử lý dữ liệu trong MongoDb là rất cần thiết. Aggregation is a framework mạnh mẽ linh hoạt trong quá trình truy vấn và xử lý dữ liệu với các toán tử mạnh mẽ cũng như hỗ trợ xử lý dữ liệu với số lượng lớn

Các lưu ý cần thiết

Các công cụ cơ bản

  • maven
  • khởi động mùa xuân
  • cơ sở dữ liệu. MongoDb (có thể tải xuống tại https. //www. mongodb. com/download-center/community lựa chọn hệ điều hành phù hợp và tải xuống)
  • phụ thuộc. Spring boot web , Spring boot data mongodb
  • Robo3T
  • Người phát thơ

Lưu ý

  • Trong loạt bài viết này sẽ trình bày xử lý Aggregation trong mùa xuân. Các thao tác xử lý cơ bản như CRUD sẽ không được cập nhật trong bài viết này. Các bạn có thể tìm hiểu thêm trên internet. Về mặt cơ bản các thuật toán CRUD trong mongoDb vẫn xử lý các lý do tương tự như trong hệ thống cơ sở dữ liệu (RDBMS). Bài viết này sẽ trình bày thêm về việc xử lý dữ liệu dựa trên con trỏ để xử lý các bản ghi vượt quá 16mb

Các thuật ngữ thường dùng trong bài viết

Khác với hệ cơ sở dữ liệu RDBMS, Spring data MongoDb sử dụng thuật ngữ khác để thực hiện ánh xạ, xử lý và thao tác trên MongoDb, Dưới đây là bảng so sánh giữa 2 hệ thống cơ sở dữ liệu và sự khác nhau của nó

MongoDbRDBMSÝ nghĩaDocumentEntityĐánh dấu đây là một lớp có thể thực hiện thao tác ánh xạ và xử lý dữ liệu với cơ sở dữ liệu, xác định tên DocumentFieldColumnXác định tên cột (với RDBMS ) hoặc tên trường với MongoDb để thực hiện ánh xạ

Bài viết sẽ thực hiện bằng cách sử dụng Thao tác tổng hợp với Bộ sưu tập tên DB là Nhân viên bao gồm các thông tin như bên dưới

/* 1 */
{
    "_id" : ObjectId("5daa7b6cd20119058c403b85"),
    "firstName" : "A",
    "lastName" : "Nguyen Van",
    "age" : 25,
    "location" : "DN",
    "salary" : 22.2
}

/* 2 */
{
    "_id" : ObjectId("5daa7b6cd20119058c403b86"),
    "firstName" : "B",
    "lastName" : "Tran Van",
    "age" : 27,
    "location" : "HN",
    "salary" : 22.7
}

/* 3 */
{
    "_id" : ObjectId("5daa7b6cd20119058c403b87"),
    "firstName" : "C",
    "lastName" : "Le Van",
    "age" : 28,
    "location" : "DN",
    "salary" : 80.2
}

Thực hiện

Trước tiên cần tiến hành tạo dự án bằng spring boot bằng cách truy cập vào trang bắt đầu. mùa xuân. io với cấu hình thông tin như bên dưới.  

Tổng hợp mongodb

Về cấu hình thông tin. Group and Artifact có thể tùy chọn đặt tên. Tuy nhiên, nên đặt theo quy tắc. com. tên công ty hoặc cá nhân. tên dự án muốn đặt. Tại mục Dependencies chọn 2 phụ thuộc là Spring Web và Spring Data Mongo Db. Lombok phụ thuộc có thể tùy chọn có hoặc không

Tiếp theo để tiến hành kết nối với cơ sở dữ liệu cơ sở dữ liệu, chúng ta cần định cấu hình kết nối với MongoDb trong các ứng dụng tệp. thuộc tính hoặc ứng dụng. yml as the bottom

Các ứng dụng. tính chất

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG

Cấu hình trên máy chủ duy nhất đang chạy ở cổng 8989, mùa xuân. dữ liệu. mongodb. uri định cấu hình kết nối với cơ sở dữ liệu với các thông số như tên người dùng là root mật khẩu là root , cổng 27017(default của mongoDb) và cơ sở dữ liệu là BaoTrung.
Các thông số tiếp theo chỉ định việc hiển thị lệnh khi thao tác với mongoDb cũng như nhật ký cấp độ khi thực hiện thao tác. Trong loạt bài viết đang sử dụng ở mức gỡ lỗi.

Có một lưu ý ở đây. Trong bài viết đang sử dụng Mongo 3. 0 Trình điều khiển Java ,cấu hình sẽ thông qua uri. Cấu hình bên dưới sẽ không thành công đối với phiên bản Mongo 3. 0 Trình điều khiển Java trở lên (chỉ áp dụng với Mongo 3. 0 Java driver trở xuống). Lý do là mùa xuân. dữ liệu. mongodb. máy chủ và mùa xuân. dữ liệu. mongodb. cổng đã bị loại bỏ trong Mongo 3. 0 Trình điều khiển Java

//Không áp dụng được với Mongo 3. 0 Trình điều khiển Java trở lên

spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=baotrung
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost

Kiểu mẫu

Thực hiện tạo một lớp có tên là Employee phía dưới

Người lao động. lớp

@Document(collection = "Employees")
public class Employee {

    @Id
    private String id;
    @Field(value = "firstName")
    @NotBlank(message = "FirstName can't empty!")
    private String firstName;
    @NotBlank(message = "LastName can't empty!")
    private String lastName;
    @NotNull
    private Integer age;
    @NotBlank(message = "Location can't empty!")
    private String location;
    private Double salary;

    public Employee() {
    }

    public Employee(String id, String firstName, String lastName, Integer age, String location, Double salary) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.location = location;
        this.salary = salary;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id='" + id + '\'' +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", age=" + age +
                ", location='" + location + '\'' +
                ", salary=" + salary +
                '}';
    }
}

Lớp trên đơn giản chỉ được sử dụng @Document xác định nó là một thực thể để có thể thao tác với MongoDb với các trường như FirstName, LastName, Salary ,Age, Location. Có một lưu ý ở đây là do ở MongoDb đang sử dụng tên tài liệu là Nhân viên nên nếu muốn ánh xạ đúng tên tài liệu tên là Nhân viên thì chúng ta sẽ sử dụng

spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=baotrung
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost
1

Tạo một tên lớp là EmployeeController và xác định các api cần thiết cho việc xử lý dữ liệu. Ở đây chúng ta sẽ xác định các api như findByLocation , computeTotalUser và calculatorSalary

Bộ điều khiển

nhân viênđiều khiển

@RestController
@RequestMapping(value = "/employees", produces = MediaType.APPLICATION_JSON_VALUE)
public class EmployeeController {

    @Autowired
    private EmployeeRepository employeeRepository;

    @GetMapping("/findByLocation")
    public ResponseEntity> fetchAllLastNameByLocation(@RequestParam String location) {
        return ResponseEntity.ok(employeeRepository.fetchAllLastNameByLocation(location));
    }

    @GetMapping("/calculateTotalUser")
    public ResponseEntity> countTotalEmployeeByLocation(@RequestParam String location) {
        return ResponseEntity.ok(employeeRepository.countTotalUserByLocation(location));
    }

    @GetMapping("/calculateSalary")
    public ResponseEntity> calculateSalaryByAgeAndLocation(@RequestParam int age, @RequestParam String location) {
        return ResponseEntity.ok(employeeRepository.calculateSalaryByAgeAndLocation(age, location));
    }
}

Lớp điều khiển phía trên sẽ xác định các api cần thiết, các tham số đầu vào và trả về phản hồi chứa dữ liệu được bao bọc trong các DTO như EmployeeResult ,EmployeeDto dựa trên thông tin của mỗi API. Các DTO này sẽ được định nghĩa bên dưới. Lưu ý rằng ở đây bộ điều khiển sẽ gọi trực tiếp đến kho lưu trữ không thông qua lớp dịch vụ hiện tại không có nhiều logic phức tạp để xử lý và đây là các trình xử lý đơn giản. Tùy theo logic và các yêu cầu mà các bạn có thể sử dụng để phù hợp trong từng dự án

Tạo giao diện với tên là EmployeeRepository và EmployeeRepositoryCustom

Kho lưu trữ nhân viên

public interface EmployeeRepository extends CrudRepository, EmployeeRepositoryCustom {

}

Nhân viênKho lưu trữ Tùy chỉnh

public interface EmployeeRepositoryCustom {

    List fetchAllLastNameByLocation(String location);
    List countTotalUserByLocation(String location);
    List calculateSalaryByAgeAndLocation(int age,String location);
}

Ở giao diện EmployeeRepositoryCustom chúng ta sẽ định cấu hình 3 method là

  • fetchAllLastNameByLocation với tham số là vị trí và trả về 1 danh sách LastName dựa trên vị trí,
  • countTotalUserByLocation với tham số là vị trí và trả về 1 danh sách tổng số người dùng theo vị trí dựa trên DTO EmployeeResult
  • TínhSalaryByAgeAndLocation với tham số là vị trí và trả về 1 danh sách các mức lương tương ứng dựa trên tuổi và vị trí

nhân viênkết quả

________số 8

nhân viênDto

package com.baotrung.springbootdemomongodb.dto;

public class EmployeeDto {
    private String _id;
    private Long totalSalary;
    private String lastName;

    public EmployeeDto() {
    }

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public Long getTotalSalary() {
        return totalSalary;
    }

    public void setTotalSalary(Long totalSalary) {
        this.totalSalary = totalSalary;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Tạo một lớp có tên là EmployeeRepositoryCustomImpl và thực hiện triển khai lại EmployeeRepositoryCustom như phía bên dưới

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
0

Chúng ta sẽ thực hiện tính toán trong 3 phương thức này bằng cách sử dụng Aggregation dựa vào MongoTemplate. Vậy MongoTemplate là gì ?
Lớp MongoTemplate, nằm trong gói org. khung mùa xuân. dữ liệu. tài liệu. mongodb, cung cấp các tính năng phong phú được thiết lập để tương tác với cơ sở dữ liệu. MongoTemplate cung cấp các phương pháp được sử dụng để tạo, cập nhật, xóa và truy vấn tài liệu MongoDB và cung cấp ánh xạ giữa các mô hình và tài liệu. Đây là một lớp rất quan trọng trong thao tác với mongoDb

Tích hợp MongoTemplate vào EmployeeRepositoryCustom như sau

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
0

Đối với phương thức fetchAllLastNameByLocation sẽ tiến hành xử lý như sau

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
1

Ở đây chúng ta có một lớp gọi là Tiêu chí. Vậy Tiêu chí là gì ? . khung mùa xuân. dữ liệu. mongodb. cốt lõi. truy vấn cung cấp nhiều phương thức để thực hiện truy vấn như WHERE , IS , LT, GT … Nó cũng cung cấp một cách tuần tự việc thực hiện các truy vấn đó

spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=baotrung
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost
2 dùng để tạo ra một tiêu chí chứa điều kiện là các vị trí trong cơ sở dữ liệu phải bằng với vị trí từ tham số đã nhập vào từ Bộ điều khiển

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
2

Câu lệnh trên được sử dụng để thực hiện tạo một đường ống có khớp toán tử (tiêu chí) với tiêu chí đã định nghĩa về phía trên và nhóm theo tên cuối cùng

Kế đến câu lệnh.
______23

sử dụng mongoTemplate thao tác với cơ sở dữ liệu với aggregation đã định nghĩa phía trên, tên bộ sưu tập là Nhân viên và trả về DTO là EmployeeDto. lớp

Cuối cùng các câu lệnh như phía dưới thực hiện tạo ra 1 danh sách các LastName với kiểu String, lấy kết quả từ các kết quả đã trả về , lặp và trả về danh sách các LastName

Kết quả khi thực hiện cuộc gọi API trên người đưa thư

Nhìn vào log trong spring, chúng ta có thể thấy dễ dàng Spring Data Mongo đã thực hiện phân tích cú pháp lệnh chúng ta viết phía sau cú pháp MongoDb theo dạng Pipeline tuần tự. khớp -> nhóm và thực hiện thao tác với MongoDb

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
3

Đối với phương thức countTotalUserByLocation sẽ thực hiện tính toán như sau

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
4

Cách thực hiện tương tự như ví dụ trên. Thực hiện việc tạo dựa trên một Tiêu chí để thực hiện tìm kiếm dựa trên Vị trí và sử dụng Aggregation để tạo các Pipeline để thực hiện theo tuần tự. Nhóm vị trí và thực hiện Đếm trên từng vị trí đó. Tuy nhiên, có 1 sự khác biệt là chúng ta sẽ sử dụng thêm một lớp là AggregationOperation để xử lý riêng cho từng toán tử như đối sánh , nhóm … Điều này làm cho mã của chúng ta rõ ràng và dễ dàng duy trì hơn. Ở đây chúng ta sẽ thực hiện lấy kết quả trực tiếp từ AggregationResults bằng phương thức getMappedResults được định nghĩa sẵn trong api của mongoDb

Kết quả khi thực hiện api. Kết quả hiển thị trên log spring.

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
5

Cũng tương tự như ví dụ về phía trên, Spring Data MongoDb dựa trên các lệnh chúng tôi đã viết để thực hiện việc tạo các Đường ống theo tuần tự. $match theo vị trí , $group theo vị trí và tính tổng dựa trên $sum

Đối với phương thức calculateSalaryByAgeAndLocation thực hiện xử lý như sau

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
6

Đối với phương thức calculateSalaryByAgeAndLocation sẽ thực hiện tính toán dựa trên 2 đk. tuổi và địa điểm. Tiêu chí sẽ thực hiện lấy những đk có tuổi lớn hơn hoặc bằng tuổi được nhập vào và vị trí bằng vị trí từ tham số được nhập vào. Toán tử AggregationOperation sẽ thực hiện tương tự các trình tự như đối sánh, nhóm theo vị trí, tổng dựa trên tiền lương và thực hiện tham chiếu đến từng Họ của Nhân viên bằng lệnh đẩy

Kết quả

Nhật ký

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
7

We can see. Spring Mongo Db đã phân tích cú pháp các câu lệnh mà chúng viết ra dưới dạng Pipeline , với các toán tử khớp. tuổi lớn hơn hoặc bằng 23, vị trí Nhóm DN theo vị trí tính tổng lương …

Thao tác MongoDb dựa trên Tập hợp với Con trỏ

Qua các ví dụ trên mongoTemplate cung cấp rất nhiều tiện ích cũng như phương thức thao tác với mongoDb. Tuy nhiên có 1 hạn chế ở đây ? . Vì sao như vậy?

Về con trỏ là gì cũng như có những phương thức nào các bạn có thể tham khảo tài liệu của MongoDb. https. // tài liệu. mongodb. com/manual/reference/method/js-cursor/?searchProperty=current&query=Cursor. Lưu ý là Cursor có các phương thức riêng để xử lý, không thể sử dụng các phương thức của bộ sưu tập để xử lý Cursor

Lưu ý. Lí do sử dụng dựa trên Con trỏ chỉ áp dụng đối với lượng dữ liệu vượt quá 16 MB. Nếu dữ liệu nhỏ hơn 16 MB, hãy sử dụng mongoTemplate. Con trỏ sử dụng sẽ khiến cơ sở dữ liệu của bạn chậm đi đáng kể dẫn đến hiệu suất không ổn định

Thao tác con trỏ trong Spring

Trước tiên chúng ta tạo 1 phương thức trong lớp EmployeeController như thế này

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
8

Phương thức này sẽ trả về 1 danh sách các LastName không trùng lặp

Tiếp theo, hãy tạo một phương thức có tên fetchAllLastNameByLocationUsedCursor trong Giao diện EmployeeRepositoryCustom và EmployeeRepositoryCustomImpl

Nhân viênKho lưu trữ Tùy chỉnh

spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=baotrung
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost
4

Impl tùy chỉnh EmployeeRepository

Tiến hành tìm tất cả các LastName dựa trên vị trí bằng Cursor

server.port=8989
spring.data.mongodb.uri=mongodb://root:[email protected]:27017/BaoTrung
spring.jpa.show-sql=true
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
logging.level.org.springframework.web = DEBUG
9

Thay vì sử dụng các Lớp nhân viên để thực hiện ánh xạ, BasicDBObject thực hiện đọc trực tiếp vào Bson với tên trường là vị trí, MongoClient xác định các kết nối như tên máy chủ, cổng, tên cơ sở dữ liệu. Phía trên tên máy chủ là localHost, cổng là 27017 và tên cơ sở dữ liệu là BaoTrung. Ở đây chúng ta sử dụng lớp DBCollection để nhận bộ sưu tập trực tiếp từ MongoClient. Bộ sưu tập được up ở đây là Nhân viên. Thực hiện tạo một Set chứa các LastName mong muốn trả về. Con trỏ con trỏ = coll. tìm (truy vấn); . Các phương thức như con trỏ. hasNext() và con trỏ. next() dùng để thực hiện tuần tự tìm kiếm trong các bảng ghi. Last Name. ví dụ thêm (((Chuỗi). get(“Họ”)));

Kết quả khi thực hiện cuộc gọi api

Đăng nhập vào mùa xuân

spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=baotrung
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost
0

Nhìn vào nhật ký có thể thấy bất kỳ Spring Data nào MongoDb đã k còn phân tích cú pháp ra các Pipeline nữa mà công việc thực hiện hoàn toàn dựa trên thao tác con trỏ trên bộ nhớ của mongoDB và trả về kết quả

Kết luận

Qua bài viết trên , mình đã giới thiệu cách sử dụng Aggregation trong spring, cách sử dụng mongoTemplate và Con trỏ. Sự khác nhau và khi nào nên sử dụng Cursor khi nào không. Hy vọng sẽ giúp mọi người hiểu thêm về Tổng hợp và tính toán tổng hợp vào dự án. Hẹn gặp lại mọi người ở các bài viết tiếp theo