mongodb-app.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /**
  2. * Module dependencies.
  3. */
  4. const cluster = require('cluster');
  5. const numCPUs = require('os').cpus().length;
  6. const express = require('express');
  7. const mongoose = require('mongoose');
  8. const connection = mongoose.createConnection('mongodb://tfb-database/hello_world',{
  9. useNewUrlParser: true,
  10. useUnifiedTopology: true,
  11. useFindAndModify: false,
  12. });
  13. // Middleware
  14. const bodyParser = require('body-parser');
  15. /**
  16. * Note! The benchmarks say we should use "id" as a property name.
  17. * However, Mongo provides a default index on "_id", so to be equivalent to the other tests, we use
  18. * the same, default index provided by the database.
  19. *
  20. */
  21. const WorldSchema = new mongoose.Schema({
  22. _id: Number,
  23. randomNumber: Number
  24. }, {
  25. collection: 'world'
  26. });
  27. const MWorld = connection.model('world', WorldSchema);
  28. const FortuneSchema = new mongoose.Schema({
  29. _id: Number,
  30. message: String
  31. }, {
  32. collection: 'fortune'
  33. });
  34. const MFortune = connection.model('fortune', FortuneSchema);
  35. if (cluster.isPrimary) {
  36. // Fork workers.
  37. for (let i = 0; i < numCPUs; i++) {
  38. cluster.fork();
  39. }
  40. cluster.on('exit', (worker, code, signal) => console.log('worker ' + worker.pid + ' died'));
  41. } else {
  42. const app = module.exports = express();
  43. const randomTfbNumber = () => Math.floor(Math.random() * 10000) + 1;
  44. const toClientWorld = (world) => {
  45. if (world) {
  46. world.id = world._id;
  47. delete world._id;
  48. }
  49. return world;
  50. };
  51. // Configuration
  52. app.use(bodyParser.urlencoded({extended: true}));
  53. // Set headers for all routes
  54. app.use((req, res, next) => {
  55. res.setHeader("Server", "Express");
  56. return next();
  57. });
  58. app.set('view engine', 'pug');
  59. app.set('views', __dirname + '/views');
  60. async function getRandomWorld() {
  61. return toClientWorld(await MWorld.findOne({_id: randomTfbNumber()}).lean().exec());
  62. }
  63. // Routes
  64. app.get('/mongooseq', async (req, res) => {
  65. const queryCount = Math.min(parseInt(req.query.queries) || 1, 500);
  66. const promises = [];
  67. for (let i = 1; i <= queryCount; i++) {
  68. promises.push(getRandomWorld());
  69. }
  70. res.send(await Promise.all(promises));
  71. });
  72. app.get('/mongoose', async (req, res) => {
  73. const result = await MWorld.findOne({_id: randomTfbNumber()}).lean().exec();
  74. res.send(toClientWorld(result));
  75. });
  76. app.get('/mongoose-fortune', async (req, res) => {
  77. const fortunes = (await MFortune.find({}).lean().exec()).map(toClientWorld);
  78. const newFortune = {id: 0, message: "Additional fortune added at request time."};
  79. fortunes.push(newFortune);
  80. fortunes.sort((a, b) => (a.message < b.message) ? -1 : 1);
  81. res.render('fortunes/index', {fortunes});
  82. });
  83. async function getUpdateRandomWorld() {
  84. // it would be nice to use findOneAndUpdate here, but for some reason the test fails with it.
  85. const world = await MWorld.findOne({_id: randomTfbNumber()}).lean().exec();
  86. world.randomNumber = randomTfbNumber();
  87. await MWorld.updateOne({
  88. _id: world._id
  89. }, {
  90. $set: {
  91. randomNumber: world.randomNumber
  92. }
  93. }).exec();
  94. return toClientWorld(world);
  95. }
  96. app.get('/mongoose-update', async (req, res) => {
  97. const queryCount = Math.min(parseInt(req.query.queries, 10) || 1, 500);
  98. const promises = [];
  99. for (let i = 1; i <= queryCount; i++) {
  100. promises.push(getUpdateRandomWorld());
  101. }
  102. res.send(await Promise.all(promises));
  103. });
  104. app.listen(8080);
  105. }