bookmark.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* eslint-disable no-return-await */
  2. const debug = require('debug')('growi:models:bookmark');
  3. const mongoose = require('mongoose');
  4. const uniqueValidator = require('mongoose-unique-validator');
  5. const ObjectId = mongoose.Schema.Types.ObjectId;
  6. module.exports = function(crowi) {
  7. const bookmarkEvent = crowi.event('bookmark');
  8. let bookmarkSchema = null;
  9. bookmarkSchema = new mongoose.Schema({
  10. page: { type: ObjectId, ref: 'Page', index: true },
  11. user: { type: ObjectId, ref: 'User', index: true },
  12. createdAt: { type: Date, default: Date.now },
  13. });
  14. bookmarkSchema.index({ page: 1, user: 1 }, { unique: true });
  15. bookmarkSchema.plugin(uniqueValidator);
  16. bookmarkSchema.statics.countByPageId = async function(pageId) {
  17. return await this.count({ page: pageId });
  18. };
  19. /**
  20. * @return {object} key: page._id, value: bookmark count
  21. */
  22. bookmarkSchema.statics.getPageIdToCountMap = async function(pageIds) {
  23. const results = await this.aggregate()
  24. .match({ page: { $in: pageIds } })
  25. .group({ _id: '$page', count: { $sum: 1 } });
  26. // convert to map
  27. const idToCountMap = {};
  28. results.forEach((result) => {
  29. idToCountMap[result._id] = result.count;
  30. });
  31. return idToCountMap;
  32. };
  33. bookmarkSchema.statics.populatePage = async function(bookmarks) {
  34. const Bookmark = this;
  35. const User = crowi.model('User');
  36. return Bookmark.populate(bookmarks, {
  37. path: 'page',
  38. populate: {
  39. path: 'lastUpdateUser', model: 'User', select: User.USER_PUBLIC_FIELDS, populate: User.IMAGE_POPULATION,
  40. },
  41. });
  42. };
  43. // bookmark チェック用
  44. bookmarkSchema.statics.findByPageIdAndUserId = function(pageId, userId) {
  45. const Bookmark = this;
  46. return new Promise(((resolve, reject) => {
  47. return Bookmark.findOne({ page: pageId, user: userId }, (err, doc) => {
  48. if (err) {
  49. return reject(err);
  50. }
  51. return resolve(doc);
  52. });
  53. }));
  54. };
  55. /**
  56. * option = {
  57. * limit: Int
  58. * offset: Int
  59. * requestUser: User
  60. * }
  61. */
  62. bookmarkSchema.statics.findByUser = function(user, option) {
  63. const Bookmark = this;
  64. const requestUser = option.requestUser || null;
  65. debug('Finding bookmark with requesting user:', requestUser);
  66. const limit = option.limit || 50;
  67. const offset = option.offset || 0;
  68. const populatePage = option.populatePage || false;
  69. return new Promise(((resolve, reject) => {
  70. Bookmark
  71. .find({ user: user._id })
  72. .sort({ createdAt: -1 })
  73. .skip(offset)
  74. .limit(limit)
  75. .exec((err, bookmarks) => {
  76. if (err) {
  77. return reject(err);
  78. }
  79. if (!populatePage) {
  80. return resolve(bookmarks);
  81. }
  82. return Bookmark.populatePage(bookmarks, requestUser).then(resolve);
  83. });
  84. }));
  85. };
  86. bookmarkSchema.statics.add = async function(page, user) {
  87. const Bookmark = this;
  88. const newBookmark = new Bookmark({ page, user, createdAt: Date.now() });
  89. try {
  90. const bookmark = await newBookmark.save();
  91. bookmarkEvent.emit('create', page._id);
  92. return bookmark;
  93. }
  94. catch (err) {
  95. if (err.code === 11000) {
  96. // duplicate key (dummy response of new object)
  97. return newBookmark;
  98. }
  99. debug('Bookmark.save failed', err);
  100. throw err;
  101. }
  102. };
  103. /**
  104. * Remove bookmark
  105. * used only when removing the page
  106. * @param {string} pageId
  107. */
  108. bookmarkSchema.statics.removeBookmarksByPageId = async function(pageId) {
  109. const Bookmark = this;
  110. try {
  111. const data = await Bookmark.remove({ page: pageId });
  112. bookmarkEvent.emit('delete', pageId);
  113. return data;
  114. }
  115. catch (err) {
  116. debug('Bookmark.remove failed (removeBookmarkByPage)', err);
  117. throw err;
  118. }
  119. };
  120. bookmarkSchema.statics.removeBookmark = async function(pageId, user) {
  121. const Bookmark = this;
  122. try {
  123. const data = await Bookmark.findOneAndRemove({ page: pageId, user });
  124. bookmarkEvent.emit('delete', pageId);
  125. return data;
  126. }
  127. catch (err) {
  128. debug('Bookmark.findOneAndRemove failed', err);
  129. throw err;
  130. }
  131. };
  132. return mongoose.model('Bookmark', bookmarkSchema);
  133. };