我有一个名为
driverTourSchema
的模式,我是这样设计的
const driverTourSchema = mongoose.Schema({
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client',
required: true,
},
userID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
liters: {
type: 'Number',
// required: true,
},
recoveryDate: {
type: Date,
required: true,
},
isRecovered: {
type: Boolean,
default: false,
},
isScheduled: {
type: Boolean,
},
});
此集合的作用是保存司机(在本例中为应用程序的用户)将进行的旅行。
有时特定日期的驾车游览是由管理员安排的。
例如我们安排在8天后,然后在集合中保存一个driverTour文档,其中包含clientID,userID和指定日期的recoveryDate。
这种类型的司机旅行被称为定期旅行,因此司机知道他要去哪里。
但是在drive Tour中,司机可以停在管理员未指定的位置,因此在这种情况下我们也需要保存它,我也将其视为driveTour的一部分。
这就是我添加 isScheduled 属性以在两组之间产生差异的原因。
我有一个表格,其中列出了根据所选时间范围进行驾车旅行的用户。 我需要显示的数据是这样的
User(name), Client(name,also client address), Total Clients(total of scheduled drive tours), totalRecoveries ( is total of recoveries made by user)
在客户总数中,我仅保存管理员创建的客户数量 因此,康复总数可能高于客户总数。
我是否需要重新设计架构以配合
Denormalization
,或者只是使用更复杂的查询。
我正在努力寻找最有效的方法。
我尝试过查找,但就资源而言这似乎很昂贵。
通过非规范化,我尝试创建另一个模式
const driverTourSummarySchema = mongoose.Schema({
userID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client'
},
totalScheduled: Number,
totalRecovered: Number
});
我写的查询是
return await DriverTour.aggregate([
{
$match: {
recoveryDate: {
$exists: true,
$gte: new Date(startDate),
$lte: new Date(endDate),
},
},
},
{
$lookup: {
from: 'users',
localField: 'userID',
foreignField: '_id',
as: 'user',
},
},
{
$unwind: '$user',
},
{
$group: {
_id: {
userID: '$userID',
recoveryDate: '$recoveryDate',
},
user: { $first: '$user.name' },
userID: { $first: '$user._id'},
totalClients: { $sum: { $cond: { if: '$isScheduled', then: 1, else: 0 } } },
totalRecoveries: { $sum: { $cond: { if: '$isRecovered', then: 1, else: 0 } } },
},
},
{
$project: {
_id: 0,
recoveryDate: '$_id.recoveryDate',
user: '$user',
userID: '$userID',
totalClients: 1,
totalRecoveries: 1,
},
},
{
$sort: {
recoveryDate: -1,
},
},
]);
还有另一种方式我需要展示
Recovery Date, User , Number_OfClients, Total_Liters_Recovered
我应该在恢复时将其保存在另一个集合中还是什么?
什么是最有效的方法。 请给我一个例子。
为了提高查询的性能,您可以考虑对架构进行非规范化。一种方法是创建一个名为 DriverTourSummarySchema 的新架构,其中包含以下字段:
const driverTourSummarySchema = mongoose.Schema({
userID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client'
},
totalScheduled: Number,
totalRecovered: Number,
totalLitersRecovered: Number
});
此架构将存储来自 DriverTourSchema 的预聚合数据,包括计划和恢复的驾驶旅行总数,以及恢复的总升数。
查询
对架构进行非规范化后,您可以使用以下查询来检索所需的数据:
查询1:
return await DriverTourSummary.aggregate([
{
$match: {
userID: {
$in: userIDs,
},
},
},
{
$project: {
user: '$userID',
totalScheduled: 1,
totalRecovered: 1,
},
},
]);
此查询将返回 userIDs 数组中每个用户计划的和恢复的驾车游览总数。
查询2:
return await DriverTour.aggregate([
{
$match: {
userID: {
$in: userIDs,
},
recoveryDate: {
$gte: new Date(startDate),
$lte: new Date(endDate),
},
},
},
{
$lookup: {
from: 'driverTourSummaries',
localField: 'userID',
foreignField: 'userID',
as: 'driverTourSummary',
},
},
{
$unwind: '$driverTourSummary',
},
{
$project: {
recoveryDate: 1,
user: '$userID',
numberOfClients: 1,
totalLitersRecovered: '$driverTourSummary.totalLitersRecovered',
},
},
{
$sort: {
recoveryDate: -1,
},
},
]);
此查询将返回指定时间范围内 userIDs 数组中每个用户的恢复日期、用户、客户端数量以及恢复的总升数。