search.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. let express = require('express')
  2. let router = express.Router()
  3. let { Post, Thread, User, Sequelize } = require('../models')
  4. const Errors = require('../lib/errors')
  5. router.get('/thread', async (req, res, next) => {
  6. try {
  7. let searchString = req.query.q
  8. let offset = +req.query.offset || 0
  9. let limit = 10
  10. /*
  11. Task is to find threads that either have the
  12. string in the title or in the content of the first post
  13. Method
  14. 1) Select first n items from each group (posts and threads), where n is the LIMIT,
  15. greater than id x, where x is previous OFFSET
  16. 2) Merge results from both, remove duplicates and sort
  17. 3) Select first n items from merged group
  18. 4) Set x as the last item from merged group
  19. */
  20. let threadTitles = await Thread.findAll({
  21. where: {
  22. name: { $like: '%' + searchString + '%' }
  23. },
  24. order: [ ['id', 'DESC'] ],
  25. include: [{
  26. model: Post,
  27. where: {
  28. postNumber: 0
  29. }
  30. }],
  31. limit,
  32. offset
  33. })
  34. let threadPosts = await Thread.findAll({
  35. order: [ ['id', 'DESC'] ],
  36. include: [{
  37. model: Post,
  38. where: {
  39. postNumber: 0,
  40. content: { $like: '%' + searchString + '%' }
  41. }
  42. }],
  43. limit,
  44. offset
  45. })
  46. let merged = [...threadTitles, ...threadPosts];
  47. let unique = [];
  48. merged.forEach(thread => {
  49. let includes = unique.filter(u => thread.id === u.id);
  50. if(!includes.length) unique.push(thread);
  51. });
  52. let sorted = unique
  53. .sort((a, b) => {
  54. return a.id - b.id;
  55. })
  56. .slice(0, limit);
  57. res.json({
  58. threads: sorted,
  59. offset: sorted.length ? sorted.slice(-1)[0].id : null,
  60. next: sorted.length < limit ? null : limit
  61. })
  62. } catch (e) { next(e) }
  63. })
  64. router.get('/user', async (req, res, next) => {
  65. try {
  66. let searchString = req.query.q
  67. let offset = +req.query.offset || 0
  68. let limit = 10
  69. let users = await User.findAll({
  70. where: {
  71. username: { $like: '%' + searchString + '%' }
  72. },
  73. order: [ ['username', 'DESC'] ],
  74. attributes: { exclude: ['hash'] },
  75. limit,
  76. offset
  77. })
  78. res.json({
  79. users,
  80. offset: users.length? users.slice(-1)[0].id : null,
  81. next: users.length < limit ? null : limit
  82. })
  83. } catch (e) { next(e) }
  84. })
  85. module.exports = router