Match trong MongoDB

Dữ liệu mùa xuân MongoDB cung cấp các trừu tượng cấp cao đơn giản cho ngôn ngữ truy vấn gốc MongoDB. Trong bài viết này, chúng ta sẽ khám phá sự hỗ trợ cho Projections and Aggregation framework

Nếu bạn chưa quen với chủ đề này, hãy tham khảo bài viết giới thiệu của chúng tôi Giới thiệu về Spring Data MongoDB

2. chiếu

Trong MongoDB, Phép chiếu là một cách để chỉ tìm nạp các trường bắt buộc của tài liệu từ cơ sở dữ liệu. Điều này làm giảm lượng dữ liệu phải truyền từ máy chủ cơ sở dữ liệu sang máy khách và do đó tăng hiệu suất

Với Spring Data MongoDB, các phép chiếu có thể được sử dụng với cả MongoTemplate và MongoRepository

Trước khi tiếp tục, hãy xem mô hình dữ liệu mà chúng ta sẽ sử dụng

@Document
public class User {
    @Id
    private String id;
    private String name;
    private Integer age;
    
    // standard getters and setters
}

2. 1. Phép chiếu sử dụng MongoTemplate

Các phương thức bao gồm [] và loại trừ [] trên lớp Trường được sử dụng để bao gồm và loại trừ các trường tương ứng

Query query = new Query[];
query.fields[].include["name"].exclude["id"];
List john = mongoTemplate.find[query, User.class];

Các phương thức này có thể được xâu chuỗi lại với nhau để bao gồm hoặc loại trừ nhiều trường. Trường được đánh dấu là @Id [_id trong cơ sở dữ liệu] luôn được tìm nạp trừ khi bị loại trừ rõ ràng

Các trường bị loại trừ là null trong thể hiện của lớp mô hình khi các bản ghi được tìm nạp bằng phép chiếu. Trong trường hợp các trường thuộc loại nguyên thủy hoặc lớp bao bọc của chúng, thì giá trị của các trường bị loại trừ là giá trị mặc định của các loại nguyên thủy

Ví dụ, String sẽ là null, int/Integer sẽ là 0 và boolean/Boolean sẽ là false

Do đó, trong ví dụ trên, trường tên sẽ là John, id sẽ là null và tuổi là 0

2. 2. Phép chiếu sử dụng MongoRepository

Trong khi sử dụng MongoRepositories, các trường của chú thích @Query có thể được xác định ở định dạng JSON

@Query[value="{}", fields="{name : 1, _id : 0}"]
List findNameAndExcludeId[];

Kết quả sẽ giống như sử dụng MongoTemplate. Giá trị =”{}” biểu thị không có bộ lọc và do đó tất cả các tài liệu sẽ được tìm nạp

3. tổng hợp

Tập hợp trong MongoDB được xây dựng để xử lý dữ liệu và trả về kết quả được tính toán. Dữ liệu được xử lý theo từng giai đoạn và đầu ra của một giai đoạn được cung cấp làm đầu vào cho giai đoạn tiếp theo. Khả năng áp dụng các phép biến đổi và tính toán trên dữ liệu theo từng giai đoạn làm cho việc tổng hợp trở thành một công cụ rất mạnh để phân tích

Dữ liệu mùa xuân MongoDB cung cấp một bản tóm tắt cho các truy vấn tổng hợp gốc bằng cách sử dụng ba lớp Tập hợp bao bọc một truy vấn tổng hợp, AggregationOperation bao bọc các giai đoạn đường ống riêng lẻ và AggregationResults là nơi chứa kết quả do tổng hợp tạo ra

Để thực hiện và tổng hợp, trước tiên, hãy tạo các đường dẫn tổng hợp bằng cách sử dụng các phương thức trình tạo tĩnh trên lớp Tập hợp, sau đó tạo một thể hiện của Tập hợp bằng phương thức newAggregation[] trên lớp Tập hợp và cuối cùng chạy tập hợp bằng MongoTemplate

MatchOperation matchStage = Aggregation.match[new Criteria["foo"].is["bar"]];
ProjectionOperation projectStage = Aggregation.project["foo", "bar.baz"];
        
Aggregation aggregation 
  = Aggregation.newAggregation[matchStage, projectStage];

AggregationResults output 
  = mongoTemplate.aggregate[aggregation, "foobar", OutType.class];

Xin lưu ý rằng cả MatchOperation và ProjectionOperation đều triển khai AggregationOperation. Có các triển khai tương tự cho các đường ống tổng hợp khác. OutType là mô hình dữ liệu cho đầu ra dự kiến

Bây giờ, chúng ta sẽ xem xét một vài ví dụ và giải thích của chúng để bao hàm các đường dẫn và toán tử tổng hợp chính

Bộ dữ liệu mà chúng tôi sẽ sử dụng trong bài viết này liệt kê chi tiết về tất cả các mã zip ở Hoa Kỳ có thể được tải xuống từ kho lưu trữ MongoDB

Hãy xem một tài liệu mẫu sau khi nhập nó vào một bộ sưu tập có tên zips trong cơ sở dữ liệu thử nghiệm

{
    "_id" : "01001",
    "city" : "AGAWAM",
    "loc" : [
        -72.622739,
        42.070206
    ],
    "pop" : 15338,
    "state" : "MA"
}

Để đơn giản và để làm cho mã ngắn gọn, trong các đoạn mã tiếp theo, chúng tôi sẽ giả sử rằng tất cả các phương thức tĩnh của lớp Tập hợp được nhập tĩnh

3. 1. Nhận tất cả các quốc gia có dân số lớn hơn 10 triệu thứ tự theo dân số giảm dần

Ở đây chúng ta sẽ có ba đường ống

  1. giai đoạn nhóm $ tổng hợp dân số của tất cả các mã zip
  2. $match giai đoạn để lọc ra các bang có dân số trên 10 triệu
  3. giai đoạn $sort để sắp xếp tất cả các tài liệu theo thứ tự dân số giảm dần

Đầu ra dự kiến ​​sẽ có trường _id là trạng thái và trường statePop với tổng dân số trạng thái. Hãy tạo một mô hình dữ liệu cho điều này và chạy tổng hợp

public class StatePoulation {
 
    @Id
    private String state;
    private Integer statePop;
 
    // standard getters and setters
}

Chú thích @Id sẽ ánh xạ trường _id từ đầu ra sang trạng thái trong mô hình

GroupOperation groupByStateAndSumPop = group["state"]
  .sum["pop"].as["statePop"];
MatchOperation filterStates = match[new Criteria["statePop"].gt[10000000]];
SortOperation sortByPopDesc = sort[Sort.by[Direction.DESC, "statePop"]];

Aggregation aggregation = newAggregation[
  groupByStateAndSumPop, filterStates, sortByPopDesc];
AggregationResults result = mongoTemplate.aggregate[
  aggregation, "zips", StatePopulation.class];

Lớp AggregationResults triển khai Iterable và do đó chúng ta có thể lặp lại nó và in kết quả

Nếu không biết mô hình dữ liệu đầu ra, lớp MongoDB tiêu chuẩn Tài liệu có thể được sử dụng

3. 2. Nhận tiểu bang nhỏ nhất theo dân số thành phố trung bình

Đối với vấn đề này, chúng ta sẽ cần bốn giai đoạn

  1. $group để tính tổng dân số của mỗi thành phố
  2. $group để tính dân số trung bình của mỗi tiểu bang
  3. giai đoạn sắp xếp $ để sắp xếp thứ tự các bang theo dân số trung bình của thành phố theo thứ tự tăng dần
  4. $limit để có được tiểu bang đầu tiên có dân số thành phố trung bình thấp nhất

Mặc dù không nhất thiết phải có, chúng tôi sẽ sử dụng giai đoạn $project bổ sung để định dạng lại tài liệu theo mô hình dữ liệu StatePopulation

GroupOperation sumTotalCityPop = group["state", "city"]
  .sum["pop"].as["cityPop"];
GroupOperation averageStatePop = group["_id.state"]
  .avg["cityPop"].as["avgCityPop"];
SortOperation sortByAvgPopAsc = sort[Sort.by[Direction.ASC, "avgCityPop"]];
LimitOperation limitToOnlyFirstDoc = limit[1];
ProjectionOperation projectToMatchModel = project[]
  .andExpression["_id"].as["state"]
  .andExpression["avgCityPop"].as["statePop"];

Aggregation aggregation = newAggregation[
  sumTotalCityPop, averageStatePop, sortByAvgPopAsc,
  limitToOnlyFirstDoc, projectToMatchModel];

AggregationResults result = mongoTemplate
  .aggregate[aggregation, "zips", StatePopulation.class];
StatePopulation smallestState = result.getUniqueMappedResult[];

Trong ví dụ này, chúng tôi đã biết rằng sẽ chỉ có một tài liệu trong kết quả vì chúng tôi giới hạn số lượng tài liệu đầu ra là 1 trong giai đoạn cuối. Như vậy, chúng ta có thể gọi getUniqueMappedResult[] để lấy thể hiện StatePopulation được yêu cầu

Một điều khác cần lưu ý là, thay vì dựa vào chú thích @Id để ánh xạ _id sang trạng thái, chúng tôi đã thực hiện nó một cách rõ ràng trong giai đoạn chiếu

3. 3. Nhận trạng thái với mã zip tối đa và tối thiểu

Đối với ví dụ này, chúng ta cần ba giai đoạn

  1. $group để đếm số lượng mã zip cho mỗi tiểu bang
  2. $sort để sắp xếp các tiểu bang theo số lượng mã zip
  3. $group để tìm trạng thái có mã zip tối đa và tối thiểu bằng toán tử $first và $last
________số 8

Ở đây chúng tôi không sử dụng bất kỳ mô hình nào mà sử dụng Tài liệu đã được cung cấp sẵn trình điều khiển MongoDB

4. Sự kết luận

Trong bài viết này, chúng ta đã học cách tìm nạp các trường được chỉ định của tài liệu trong MongoDB bằng cách sử dụng các phép chiếu trong Spring Data MongoDB

Chúng tôi cũng đã tìm hiểu về hỗ trợ khung tổng hợp MongoDB trong Dữ liệu mùa xuân. Chúng tôi đã đề cập đến các giai đoạn tổng hợp chính – nhóm, dự án, sắp xếp, giới hạn và đối sánh và xem xét một số ví dụ về các ứng dụng thực tế của nó. Mã nguồn hoàn chỉnh có sẵn trên GitHub

Chủ Đề