家人们!今天咱要勇闯 MongoDB 聚合操作的 "数据魔法学院"!这玩意儿就像数据库界的 "满汉全席厨师",能把杂乱无章的数据食材,加工成老板看了直呼 "好家伙" 的分析报表!不管你是刚入门的小白,还是想进阶的老鸟,跟着我这波操作,保准让你从 "厨房帮工" 变身 "米其林大厨"!
一、食材准备:定义数据菜单
先给大家瞅瞅咱们的 "数据菜谱"------ 假设咱有个 orders 集合,专门存订单信息,每个文档长这样:
json
{
"orderId": "123",
"customer": "Alice",
"products": [
{
"productName": "Laptop",
"price": 1000,
"quantity": 1
},
{
"productName": "Mouse",
"price": 20,
"quantity": 2
}
],
"orderDate": "2024-01-01"
}
有了这些数据食材,咱们的聚合魔法盛宴正式开席!
二、基础操作:厨房入门三件套
1. $match:食材质检员
$match 堪称数据界的 "质检员",专门把不符合要求的食材挑出去!比如咱们只要 2024 年 1 月 1 日后的订单:
ini
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Filters.gt;
public class MatchExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:db.orders.aggregate([{ $match: { orderDate: { $gt: "2024-01-01" } } }])
AggregateIterable<Document> result = collection.aggregate(List.of(
match(gt("orderDate", "2024-01-01"))
));
for (Document document : result) {
System.out.println(document);
}
}
}
这波操作,就像把过期食材全扔了,只留下新鲜的!
2. $project:食材整形师
$project 是数据界的 "整形医生",能决定哪些字段要 "露脸"!比如咱们只要 orderId 和 customer 字段:
ini
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;
public class ProjectExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:db.orders.aggregate([{ $project: { orderId: 1, customer: 1, _id: 0 } }])
AggregateIterable<Document> result = collection.aggregate(List.of(
project(fields(include("orderId", "customer"), include("_id", 0)))
));
for (Document document : result) {
System.out.println(document);
}
}
}
这就好比给数据做了个 "美颜",只留下咱想看的部分!
3. $sort:食材排序员
$sort 是数据界的 "强迫症晚期患者",非要把数据按顺序排得明明白白!比如按订单日期降序排列:
ini
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.sort;
import static com.mongodb.client.model.Sorts.descending;
public class SortExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:db.orders.aggregate([{ $sort: { orderDate: -1 } }])
AggregateIterable<Document> result = collection.aggregate(List.of(
sort(descending("orderDate"))
));
for (Document document : result) {
System.out.println(document);
}
}
}
这下数据全都整整齐齐,找起来超方便!
三、中级操作:进阶烹饪技巧
1. $group:食材分类员
$group 就像超市的 "货架管理员",把相似的数据分到同一类!比如统计每个客户的订单总金额:
dart
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.group;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Aggregates.unwind;
import static com.mongodb.client.model.Accumulators.sum;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;
public class GroupExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:
// db.orders.aggregate([
// { $unwind: "$products" },
// {
// $group: {
// _id: "$customer",
// totalAmount: { $sum: { $multiply: [ "$products.price", "$products.quantity" ] } }
// }
// },
// {
// $project: {
// customer: "$_id",
// totalAmount: 1,
// _id: 0
// }
// }
// ])
AggregateIterable<Document> result = collection.aggregate(List.of(
unwind("$products"),
group("$customer", sum("totalAmount", new Document("$multiply", Arrays.asList("$products.price", "$products.quantity")))),
project(fields(include("customer", "$_id"), include("totalAmount"), include("_id", 0)))
));
for (Document document : result) {
System.out.println(document);
}
}
}
有了这招,老板问 "每个客户花了多少钱",咱直接甩数据,超有排面!
2. $unwind:食材拆解师
<math xmlns="http://www.w3.org/1998/Math/MathML"> u n w i n d 就像把一捆菜拆开的"拆包大师",专门对付数组类型的数据!在上面 unwind 就像把一捆菜拆开的 "拆包大师",专门对付数组类型的数据!在上面 </math>unwind就像把一捆菜拆开的"拆包大师",专门对付数组类型的数据!在上面group 算总金额时,就用它拆开 products 数组:
ini
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.unwind;
public class UnwindExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:db.orders.aggregate([{ $unwind: "$products" }])
AggregateIterable<Document> result = collection.aggregate(List.of(
unwind("$products")
));
for (Document document : result) {
System.out.println(document);
}
}
}
这操作,让复杂的数组数据瞬间变得 "服服帖帖"!
四、高阶操作:顶级烹饪秘籍
1. $lookup:跨仓库取材
$lookup 简直是数据界的 "哆啦 A 梦",能从别的集合里 "掏" 数据过来!假设咱有个 customers 集合存客户详情,想把订单和客户信息关联起来:
typescript
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.lookup;
public class LookupExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:
// db.orders.aggregate([
// {
// $lookup: {
// from: "customers",
// localField: "customer",
// foreignField: "name",
// as: "customerDetails"
// }
// }
// ])
AggregateIterable<Document> result = collection.aggregate(List.of(
lookup("customers", "customer", "name", "customerDetails")
));
for (Document document : result) {
System.out.println(document);
}
}
}
这波操作,就像把不同仓库的食材凑到一起,做出超豪华套餐!
2. $facet:同时做大餐
$facet 是数据界的 "时间管理大师",能同时执行多个聚合任务!比如咱同时统计每个客户的订单数和总金额:
dart
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import static com.mongodb.client.model.Aggregates.facet;
import static com.mongodb.client.model.Aggregates.group;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Aggregates.unwind;
import static com.mongodb.client.model.Accumulators.sum;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;
public class FacetExample {
public static void main(String[] args) {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection = database.getCollection("orders");
// 对应MongoDB查询语句:
// db.orders.aggregate([
// {
// $facet: {
// orderCountByCustomer: [
// {
// $group: {
// _id: "$customer",
// orderCount: { $sum: 1 }
// }
// },
// {
// $project: {
// customer: "$_id",
// orderCount: 1,
// _id: 0
// }
// }
// ],
// totalAmountByCustomer: [
// { $unwind: "$products" },
// {
// $group: {
// _id: "$customer",
// totalAmount: { $sum: { $multiply: [ "$products.price", "$products.quantity" ] } }
// }
// },
// {
// $project: {
// customer: "$_id",
// totalAmount: 1,
// _id: 0
// }
// }
// ]
// }
// }
// ])
AggregateIterable<Document> result = collection.aggregate(List.of(
facet(
"orderCountByCustomer", Arrays.asList(
group("$customer", sum("orderCount", 1)),
project(fields(include("customer", "$_id"), include("orderCount"), include("_id", 0)))
),
"totalAmountByCustomer", Arrays.asList(
unwind("$products"),
group("$customer", sum("totalAmount", new Document("$multiply", Arrays.asList("$products.price", "$products.quantity")))),
project(fields(include("customer", "$_id"), include("totalAmount"), include("_id", 0)))
)
)
));
for (Document document : result) {
System.out.println(document);
}
}
}
这波操作,就像同时炒好几道菜,效率直接拉满!
五、总结:毕业成大厨
到这儿,MongoDB 聚合操作的 "十八般武艺" 咱算是学了个七七八八!从基础的筛选、投影,到中级的分组、拆解,再到高阶的跨集合关联、多任务处理,每一招都能在实际项目中大显身手。
不过,光看教程可成不了大厨!赶紧去自己的项目里实操,多试试不同的操作组合。要是遇到 "翻车现场",欢迎来评论区吐槽,咱们一起把这些 "坑" 填平!觉得这篇文章有用的,点赞、收藏、转发三连安排上,让更多小伙伴一起玩转 MongoDB 聚合操作!下次咱们再解锁更多数据库的 "隐藏技能",不见不散!