Renamed to winners. Winners gets controller setup.
Rewrote everything that happened in history to better take advantage of monogdb instead of doing everything in js. Our endpoints become: - /winners - getAll w/ includeWines and sort query params. - /winners/latest - latest winners grouped w/ includeWines query params. - /winners/by-date - all winners grouped by date w/ includeWines and sort. - /winners/by-date/:date - get winners per epoch or string date. - /winners/by-name/:name - get winner by name parameter w/ sort for wins direction.
This commit is contained in:
		@@ -1,92 +0,0 @@
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const historyRepository = require(path.join(__dirname, "../history"));
 | 
			
		||||
 | 
			
		||||
const all = (req, res) => {
 | 
			
		||||
  return historyRepository
 | 
			
		||||
    .all()
 | 
			
		||||
    .then(lotteries =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        lotteries: lotteries,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch history."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const latest = (req, res) => {
 | 
			
		||||
  return historyRepository
 | 
			
		||||
    .latest()
 | 
			
		||||
    .then(lottery =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        lottery: lottery,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch latest history."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byDate = (req, res) => {
 | 
			
		||||
  let { date } = req.params;
 | 
			
		||||
  date = new Date(new Date(parseInt(date)).setHours(0, 0, 0, 0)).getTime();
 | 
			
		||||
 | 
			
		||||
  return historyRepository
 | 
			
		||||
    .byEpochDate(date)
 | 
			
		||||
    .then(winners =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        date: date,
 | 
			
		||||
        winners: winners,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch history for date."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byName = (req, res) => {
 | 
			
		||||
  const { name } = req.params;
 | 
			
		||||
 | 
			
		||||
  return historyRepository
 | 
			
		||||
    .byName(name)
 | 
			
		||||
    .then(lotteries =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        name: name,
 | 
			
		||||
        lotteries: lotteries,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch history for name."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  all,
 | 
			
		||||
  latest,
 | 
			
		||||
  byDate,
 | 
			
		||||
  byName
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										165
									
								
								api/controllers/winnerController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								api/controllers/winnerController.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const winnerRepository = require(path.join(__dirname, "../winner"));
 | 
			
		||||
 | 
			
		||||
const sortOptions = ["desc", "asc"];
 | 
			
		||||
const includeWinesOptions = ["true", "false"];
 | 
			
		||||
 | 
			
		||||
const all = (req, res) => {
 | 
			
		||||
  let { sort, includeWines } = req.query;
 | 
			
		||||
 | 
			
		||||
  if (sort !== undefined && !sortOptions.includes(sort)) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: `Sort option must be: '${sortOptions.join(", ")}'`,
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (includeWines !== undefined && !includeWinesOptions.includes(includeWines)) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: `includeWines option must be: '${includeWinesOptions.join(", ")}'`,
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return winnerRepository
 | 
			
		||||
    .all(includeWines == "true")
 | 
			
		||||
    .then(winners =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        winners: sort !== "asc" ? winners : winners.reverse(),
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch winners."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byDate = (req, res) => {
 | 
			
		||||
  let { date } = req.params;
 | 
			
		||||
 | 
			
		||||
  const regexDate = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
 | 
			
		||||
  if (!isNaN(date)) {
 | 
			
		||||
    date = new Date(new Date(parseInt(date * 1000)).setHours(0, 0, 0, 0));
 | 
			
		||||
  } else if (regexDate.test(date)) {
 | 
			
		||||
    date = new Date(date);
 | 
			
		||||
  } else if (date !== undefined) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: "Invalid date parameter, allowed epoch seconds or YYYY-MM-DD.",
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return winnerRepository
 | 
			
		||||
    .byDate(date)
 | 
			
		||||
    .then(winners =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        date: date,
 | 
			
		||||
        winners: winners,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch winner by date."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const groupedByDate = (req, res) => {
 | 
			
		||||
  let { sort, includeWines } = req.query;
 | 
			
		||||
 | 
			
		||||
  if (sort !== undefined && !sortOptions.includes(sort)) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: `Sort option must be: '${sortOptions.join(", ")}'`,
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (includeWines !== undefined && !includeWinesOptions.includes(includeWines)) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: `includeWines option must be: '${includeWinesOptions.join(", ")}'`,
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return winnerRepository
 | 
			
		||||
    .groupedByDate(includeWines, sort)
 | 
			
		||||
    .then(lotteries =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        lotteries: lotteries,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch winner by date."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const latest = (req, res) => {
 | 
			
		||||
  return winnerRepository
 | 
			
		||||
    .latest()
 | 
			
		||||
    .then(winners =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        ...winners,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch winner by date."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byName = (req, res) => {
 | 
			
		||||
  const { name } = req.params;
 | 
			
		||||
  const { sort } = req.query;
 | 
			
		||||
 | 
			
		||||
  if (sort !== undefined && !sortOptions.includes(sort)) {
 | 
			
		||||
    return res.status(400).send({
 | 
			
		||||
      message: `Sort option must be: '${sortOptions.join(", ")}'`,
 | 
			
		||||
      success: false
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return winnerRepository
 | 
			
		||||
    .byName(name, sort)
 | 
			
		||||
    .then(winner =>
 | 
			
		||||
      res.send({
 | 
			
		||||
        winner: winner,
 | 
			
		||||
        success: true
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      const { statusCode, message } = error;
 | 
			
		||||
 | 
			
		||||
      return res.status(statusCode || 500).send({
 | 
			
		||||
        success: false,
 | 
			
		||||
        message: message || "Unable to fetch winner by name."
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  all,
 | 
			
		||||
  byDate,
 | 
			
		||||
  groupedByDate,
 | 
			
		||||
  latest,
 | 
			
		||||
  byName
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										117
									
								
								api/history.js
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								api/history.js
									
									
									
									
									
								
							@@ -1,117 +0,0 @@
 | 
			
		||||
const path = require("path");
 | 
			
		||||
 | 
			
		||||
const Highscore = 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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Utils
 | 
			
		||||
const epochToDateString = date => new Date(parseInt(date)).toDateString();
 | 
			
		||||
 | 
			
		||||
const sortNewestFirst = lotteries => {
 | 
			
		||||
  return lotteries.sort((a, b) => (parseInt(a.date) < parseInt(b.date) ? 1 : -1));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const groupHighscoreByDate = async (highscore = undefined) => {
 | 
			
		||||
  if (highscore == undefined) highscore = await Highscore.find();
 | 
			
		||||
 | 
			
		||||
  const highscoreByDate = [];
 | 
			
		||||
 | 
			
		||||
  highscore.forEach(person => {
 | 
			
		||||
    person.wins.map(win => {
 | 
			
		||||
      const epochDate = new Date(win.date).setHours(0, 0, 0, 0);
 | 
			
		||||
      const winnerObject = {
 | 
			
		||||
        name: person.name,
 | 
			
		||||
        color: win.color,
 | 
			
		||||
        wine: win.wine,
 | 
			
		||||
        date: epochDate
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const existingDateIndex = highscoreByDate.findIndex(el => el.date == epochDate);
 | 
			
		||||
      if (existingDateIndex > -1) highscoreByDate[existingDateIndex].winners.push(winnerObject);
 | 
			
		||||
      else
 | 
			
		||||
        highscoreByDate.push({
 | 
			
		||||
          date: epochDate,
 | 
			
		||||
          winners: [winnerObject]
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return sortNewestFirst(highscoreByDate);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const resolveWineReferences = (highscoreObject, key) => {
 | 
			
		||||
  const listWithWines = highscoreObject[key];
 | 
			
		||||
 | 
			
		||||
  return Promise.all(
 | 
			
		||||
    listWithWines.map(element =>
 | 
			
		||||
      Wine.findById(element.wine).then(wine => {
 | 
			
		||||
        element.wine = wine;
 | 
			
		||||
        return element;
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
  ).then(resolvedListWithWines => {
 | 
			
		||||
    highscoreObject[key] = resolvedListWithWines;
 | 
			
		||||
    return highscoreObject;
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
// end utils
 | 
			
		||||
 | 
			
		||||
// Routes
 | 
			
		||||
const all = () => {
 | 
			
		||||
  return Highscore.find().then(highscore => groupHighscoreByDate(highscore));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const latest = () => {
 | 
			
		||||
  return groupHighscoreByDate()
 | 
			
		||||
    .then(lotteries => lotteries.shift()) // first element in list
 | 
			
		||||
    .then(latestLottery => resolveWineReferences(latestLottery, "winners"));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byEpochDate = date => {
 | 
			
		||||
  return groupHighscoreByDate()
 | 
			
		||||
    .then(lotteries => {
 | 
			
		||||
      const lottery = lotteries.filter(lottery => lottery.date == date);
 | 
			
		||||
      if (lottery.length > 0) {
 | 
			
		||||
        return lottery[0];
 | 
			
		||||
      } else {
 | 
			
		||||
        throw new HistoryByDateNotFound();
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    .then(lottery => resolveWineReferences(lottery, "winners"))
 | 
			
		||||
    .then(lottery => lottery.winners);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const byName = name => {
 | 
			
		||||
  return Highscore.find({ name })
 | 
			
		||||
    .then(highscore => {
 | 
			
		||||
      if (highscore.length > 0) {
 | 
			
		||||
        return highscore[0];
 | 
			
		||||
      } else {
 | 
			
		||||
        throw new HistoryForUserNotFound();
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    .then(highscore => resolveWineReferences(highscore, "wins"))
 | 
			
		||||
    .then(highscore => sortNewestFirst(highscore.wins));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  all,
 | 
			
		||||
  latest,
 | 
			
		||||
  byEpochDate,
 | 
			
		||||
  byName
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										191
									
								
								api/winner.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								api/winner.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
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") => {
 | 
			
		||||
  const populateOptions = { sort: "date" };
 | 
			
		||||
 | 
			
		||||
  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 groupedByDate = (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()));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  all,
 | 
			
		||||
  byDate,
 | 
			
		||||
  latest,
 | 
			
		||||
  groupedByDate
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user