我的应用类似于一个手机号码缴费的系统,根据手机号码的缴费订单之前销售的代理商进行返利。 当前的表结构如下: users: // 用户表,当前记录150 条 { _id: ObjectId; acceptOrder: [ObjectId]; // 订单 id }
orders: // 号码订单表,当前记录 600 条
{
_id: ObjectId;
haveNo: [ObjectId]; // 号码 id
}
rechargeOrders: // 充值订单表,当前记录 20k 条
{
_id: ObjectId;
_simcardNo: ObjectId; // 号码 id
fee: Number; // 充值金额
createdAt: Date; // 充值时间
paid: Boolean; // 话费是否已经支付
rebatePaid: Boolean; // 返利是否已经支付
}
当前需要按照用户的维度统计应结算的返利,代码(删减版)如下:
db.users.aggregate([
{$unwind: "$acceptOrder"},
{$project: {_id: "$_id", acceptOrder: "$acceptOrder"}},
{$lookup: {
from: "orders",
localField: "acceptOrder",
foreignField: "_id",
as: "orders"
}},
{$unwind: "$orders"},
{$project: {_id: "$_id", haveNo: "$orders.haveNo"}},
{$unwind: "$haveNo"},
{$lookup: {
from: "rechargeorders",
localField: "haveNo",
foreignField: "_simcardId",
as: "rechargeOrders"
}},
{$unwind: "$rechargeOrders"},
{$match: { "rechargeOrders.paid": true, "rechargeOrders.createdAt": {$lt: ISODate("2017-01-11T00:00:00.000+08:00") }}},
{$project: {_id: "$_id", fee: "$rechargeOrders.fee"}},
{$group: {
_id: {_id: "$_id", company: "$company"},
fee: {$sum: "$fee"},
count: {$sum: 1}
}}
])
当前的数据库版本为3.4.1。每个表的_id字段和一对多的数组都设置了索引。当前出现的问题是,在这样的数量级的情况下,使用上面的语句查询起来需要1700s左右。经过分析,瓶颈应该是在加上$group这句之后,在$group之前的语句最多只需要3s的时间。实在不知道应该如何优化?