ProjectSampler.mjs 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // @ts-check
  2. import { objectIdFromDate } from './utils.mjs'
  3. import { db } from '../storage/lib/mongodb.js'
  4. import config from 'config'
  5. const projectsCollection = db.collection('projects')
  6. const HAS_PROJECTS_WITHOUT_HISTORY =
  7. config.get('hasProjectsWithoutHistory') === 'true'
  8. /**
  9. * @param {Date} start
  10. * @param {Date} end
  11. * @param {number} N
  12. * @return {Promise<Array<string>>}
  13. */
  14. export async function selectProjectsInDateRange(start, end, N) {
  15. let projects = await projectsCollection
  16. .aggregate([
  17. {
  18. $match: {
  19. _id: {
  20. $gt: objectIdFromDate(start),
  21. $lte: objectIdFromDate(end),
  22. },
  23. },
  24. },
  25. { $sample: { size: N } },
  26. { $project: { 'overleaf.history.id': 1 } },
  27. ])
  28. .toArray()
  29. if (HAS_PROJECTS_WITHOUT_HISTORY) {
  30. projects = projects.filter(p => Boolean(p.overleaf?.history?.id))
  31. if (projects.length === 0) {
  32. // Very unlucky sample. Try again.
  33. return await selectProjectsInDateRange(start, end, N)
  34. }
  35. }
  36. return projects.map(p => p.overleaf.history.id.toString())
  37. }
  38. export async function* getSampleProjectsCursor(N) {
  39. const cursor = projectsCollection.aggregate([
  40. { $sample: { size: N } },
  41. { $project: { 'overleaf.history.id': 1 } },
  42. ])
  43. let validProjects = 0
  44. for await (const project of cursor) {
  45. if (HAS_PROJECTS_WITHOUT_HISTORY) {
  46. continue
  47. }
  48. validProjects++
  49. yield project.overleaf.history.id.toString()
  50. }
  51. if (validProjects === 0) {
  52. yield* getSampleProjectsCursor(N)
  53. }
  54. }