Winner controller replaces a lot of what happens in retrieve did for aggregating when and what had been won. Now this is more clearly defined in winner.js. Also leverage mongo's query more than sorting and aggregating data like previous implementation where a lot happened in js.
288 lines
5.2 KiB
JavaScript
288 lines
5.2 KiB
JavaScript
const path = require("path");
|
|
|
|
const Winner = require(path.join(__dirname, "/schemas/Highscore"));
|
|
const Wine = require(path.join(__dirname, "/schemas/Wine"));
|
|
|
|
class HistoryByDateNotFound extends Error {
|
|
constructor(message = "History for given date not found.") {
|
|
super(message);
|
|
this.name = "HistoryByDateNotFound";
|
|
this.statusCode = 404;
|
|
}
|
|
}
|
|
|
|
class HistoryForUserNotFound extends Error {
|
|
constructor(message = "History for given user not found.") {
|
|
super(message);
|
|
this.name = "HistoryForUserNotFound";
|
|
this.statusCode = 404;
|
|
}
|
|
}
|
|
|
|
const all = (includeWines = false) => {
|
|
if (includeWines === false) {
|
|
return Winner.find().sort("-wins.date");
|
|
} else {
|
|
return Winner.find()
|
|
.sort("-wins.date")
|
|
.populate("wins.wine");
|
|
}
|
|
};
|
|
|
|
const byDate = date => {
|
|
const startQueryDate = new Date(date.setHours(0, 0, 0, 0));
|
|
const endQueryDate = new Date(date.setHours(24, 59, 59, 99));
|
|
const query = [
|
|
{
|
|
$match: {
|
|
"wins.date": {
|
|
$gte: startQueryDate,
|
|
$lte: endQueryDate
|
|
}
|
|
}
|
|
},
|
|
{ $unwind: "$wins" },
|
|
{
|
|
$match: {
|
|
"wins.date": {
|
|
$gte: startQueryDate,
|
|
$lte: endQueryDate
|
|
}
|
|
}
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: "wines",
|
|
localField: "wins.wine",
|
|
foreignField: "_id",
|
|
as: "wins.wine"
|
|
}
|
|
},
|
|
{ $unwind: "$wins.wine" },
|
|
{
|
|
$project: {
|
|
name: "$name",
|
|
date: "$wins.date",
|
|
color: "$wins.color",
|
|
wine: "$wins.wine"
|
|
}
|
|
}
|
|
];
|
|
|
|
return Winner.aggregate(query).then(winners => {
|
|
if (winners.length == 0) {
|
|
throw new HistoryByDateNotFound();
|
|
}
|
|
return winners;
|
|
});
|
|
};
|
|
|
|
const byName = (name, sort = "desc") => {
|
|
return Winner.findOne({ name }, ["name", "wins"])
|
|
.sort("-wins.date")
|
|
.populate("wins.wine")
|
|
.then(winner => {
|
|
if (winner) {
|
|
winner.wins = sort !== "asc" ? winner.wins.reverse() : winner.wins;
|
|
return winner;
|
|
} else {
|
|
throw new HistoryForUserNotFound();
|
|
}
|
|
});
|
|
};
|
|
|
|
const latest = () => {
|
|
const query = [
|
|
{
|
|
$unwind: "$wins"
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: "wines",
|
|
localField: "wins.wine",
|
|
foreignField: "_id",
|
|
as: "wins.wine"
|
|
}
|
|
},
|
|
{
|
|
$group: {
|
|
_id: "$wins.date",
|
|
winners: {
|
|
$push: {
|
|
_id: "$_id",
|
|
name: "$name",
|
|
color: "$wins.color",
|
|
wine: "$wins.wine"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
$project: {
|
|
date: "$_id",
|
|
winners: "$winners"
|
|
}
|
|
},
|
|
{
|
|
$sort: {
|
|
_id: -1
|
|
}
|
|
},
|
|
{
|
|
$limit: 1
|
|
}
|
|
];
|
|
|
|
return Winner.aggregate(query).then(winners => winners[0]);
|
|
};
|
|
|
|
const groupByDate = (includeWines = false, sort = "desc") => {
|
|
const query = [
|
|
{
|
|
$unwind: "$wins"
|
|
},
|
|
{
|
|
$group: {
|
|
_id: "$wins.date",
|
|
winners: {
|
|
$push: {
|
|
_id: "$_id",
|
|
name: "$name",
|
|
color: "$wins.color",
|
|
wine: "$wins.wine"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
$project: {
|
|
date: "$_id",
|
|
winners: "$winners"
|
|
}
|
|
},
|
|
{
|
|
$sort: {
|
|
_id: -1
|
|
}
|
|
}
|
|
];
|
|
|
|
if (includeWines) {
|
|
query.splice(1, 0, {
|
|
$lookup: {
|
|
from: "wines",
|
|
localField: "wins.wine",
|
|
foreignField: "_id",
|
|
as: "wins.wine"
|
|
}
|
|
});
|
|
}
|
|
|
|
return Winner.aggregate(query).then(lotteries => (sort != "asc" ? lotteries : lotteries.reverse()));
|
|
};
|
|
|
|
const groupByColor = (includeWines = false) => {
|
|
const query = [
|
|
{
|
|
$unwind: "$wins"
|
|
},
|
|
{
|
|
$group: {
|
|
_id: "$wins.color",
|
|
winners: {
|
|
$push: {
|
|
_id: "$_id",
|
|
name: "$name",
|
|
date: "$wins.date",
|
|
wine: "$wins.wine"
|
|
}
|
|
},
|
|
count: { $sum: 1 }
|
|
}
|
|
},
|
|
{
|
|
$project: {
|
|
color: "$_id",
|
|
count: "$count",
|
|
winners: "$winners"
|
|
}
|
|
},
|
|
{
|
|
$sort: {
|
|
_id: -1
|
|
}
|
|
}
|
|
];
|
|
|
|
if (includeWines) {
|
|
query.splice(1, 0, {
|
|
$lookup: {
|
|
from: "wines",
|
|
localField: "wins.wine",
|
|
foreignField: "_id",
|
|
as: "wins.wine"
|
|
}
|
|
});
|
|
}
|
|
|
|
return Winner.aggregate(query);
|
|
};
|
|
|
|
const orderByWins = (includeWines = false) => {
|
|
let query = [
|
|
{
|
|
$project: {
|
|
name: "$name",
|
|
wins: "$wins",
|
|
totalWins: { $size: "$wins" }
|
|
}
|
|
},
|
|
{
|
|
$sort: {
|
|
totalWins: -1,
|
|
"wins.date": -1
|
|
}
|
|
}
|
|
];
|
|
|
|
if (includeWines) {
|
|
const includeWinesSubQuery = [
|
|
{
|
|
$unwind: "$wins"
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: "wines",
|
|
localField: "wins.wine",
|
|
foreignField: "_id",
|
|
as: "wins.wine"
|
|
}
|
|
},
|
|
{
|
|
$unwind: "$wins._id"
|
|
},
|
|
{
|
|
$group: {
|
|
_id: "$_id",
|
|
name: { $first: "$name" },
|
|
totalWins: { $first: "$totalWins" },
|
|
wins: { $push: "$wins" }
|
|
}
|
|
}
|
|
];
|
|
|
|
query = includeWinesSubQuery.concat(query);
|
|
}
|
|
|
|
return Winner.aggregate(query);
|
|
};
|
|
|
|
module.exports = {
|
|
all,
|
|
byDate,
|
|
latest,
|
|
groupByDate,
|
|
groupByColor,
|
|
orderByWins
|
|
};
|