Tổng quan
Lớp tiện ích dưới đây cung cấp các phương thức cơ bản để thao tác với MongoDB trong dự án Spring Boot, bao gồm: tạo chỉ mục, truy vấn điều kiện, phân trang, cập nhật dữ liệu và các phép toán aggregation.
Cài đặt lớp tiện ích
package com.example.mongo.util;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class MongoUtils {
private static MongoTemplate template;
@Autowired
public void setMongoTemplate(MongoTemplate mongoTemplate) {
template = mongoTemplate;
}
// Lưu danh sách bản ghi vào collection
public static <T> void saveBatch(String collection, List<T> records) {
records.forEach(record -> template.save(record, collection));
}
// Tạo chỉ mục hợp nhất
public static void createCompoundIndex(String collection, String indexName, Map<String, Sort.Direction> fields) {
Index index = new Index().named(indexName);
fields.forEach((field, direction) -> index.on(field, direction));
template.indexOps(collection).ensureIndex(index);
}
// Truy vấn phân trang có điều kiện
public static <T> Map<String, Object> findPaginated(Class<T> clazz, String collection,
Map<String, Object> filters,
int page, int size,
String sortField, Sort.Direction direction) {
Criteria criteria = buildCriteria(filters);
long total = template.count(Query.query(criteria), clazz, collection);
Query query = Query.query(criteria)
.skip((page-1)*size)
.limit(size)
.with(Sort.by(direction, sortField));
List<T> results = template.find(query, clazz, collection);
Map<String, Object> response = new HashMap<>();
response.put("data", results);
response.put("total", total);
response.put("pages", (int)Math.ceil((double)total/size));
return response;
}
// Cập nhật nhiều bản ghi theo điều kiện
public static void updateMultiple(String collection, String matchField, Object matchValue,
Map<String, Object> updateFields) {
Query query = Query.query(Criteria.where(matchField).is(matchValue));
Update update = new Update();
updateFields.forEach((k, v) -> update.set(k, v));
template.updateMulti(query, update, collection);
}
// Tính tổng giá trị trường số
public static Double calculateSum(String collection, Class<?> clazz,
Map<String, Object> filters, String sumField) {
Criteria criteria = buildCriteria(filters);
MatchOperation match = Aggregation.match(criteria);
GroupOperation group = Aggregation.group().sum(sumField).as("total");
return template.aggregate(Aggregation.newAggregation(match, group),
collection, Map.class)
.getMappedResults()
.stream()
.findFirst()
.map(result -> (Double)result.get("total"))
.orElse(0.0);
}
private static Criteria buildCriteria(Map<String, Object> filters) {
Criteria criteria = new Criteria();
if (filters == null || filters.isEmpty()) return criteria;
List<Criteria> conditions = new ArrayList<>();
filters.forEach((key, value) ->
conditions.add(Criteria.where(key).is(value)));
return criteria.andOperator(conditions.toArray(new Criteria[0]));
}
}
Lớp mô hình phân trang
package com.example.mongo.model;
import java.util.List;
public class PaginationResult<T> {
private List<T> data;
private long totalItems;
private int totalPages;
private int currentPage;
// Constructor, Getter/Setter
}
Ví dụ sử dụng
// Lưu dữ liệu
List<Product> products = Arrays.asList(new Product("Laptop"), new Product("Smartphone"));
MongoUtils.saveBatch("products", products);
// Tạo chỉ mục
Map<String, Sort.Direction> indexFields = new HashMap<>();
indexFields.put("category", Sort.Direction.ASC);
indexFields.put("price", Sort.Direction.DESC);
MongoUtils.createCompoundIndex("products", "category_price_index", indexFields);
// Truy vấn phân trang
Map<String, Object> filters = Map.of("status", "active");
var result = MongoUtils.findPaginated(Product.class, "products",
filters, 1, 10, "price", Sort.Direction.DESC);