From 7ee385fe45e9e64865e75292380bc8832eebeea6 Mon Sep 17 00:00:00 2001 From: Eric Mc Sween <5454374+emcsween@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:46:38 -0400 Subject: [PATCH] Merge pull request #34816 from overleaf/revert-34643-em-library-backend-search Revert "Library search: make backend search tokens consistent with frontend (follow-up to #34386)" GitOrigin-RevId: 83328f2ee4a9c3f668325fa4de1ca652e7c718bf --- services/web/.storybook/main.ts | 1 - .../backfill_library_references_search.mjs | 69 ++++++++++++------- services/web/tsconfig.backend.json | 1 - services/web/tsconfig.json | 2 - ...e_libraryReferences_searchTokens_index.mjs | 26 ------- 5 files changed, 44 insertions(+), 55 deletions(-) delete mode 100644 tools/migrations/20260612120000_replace_libraryReferences_searchTokens_index.mjs diff --git a/services/web/.storybook/main.ts b/services/web/.storybook/main.ts index 462e56cfb8..fc0672e6e0 100644 --- a/services/web/.storybook/main.ts +++ b/services/web/.storybook/main.ts @@ -121,7 +121,6 @@ export default defineMain({ ...storybookConfig.resolve?.alias, // custom prefixes for import paths '@': path.join(rootDir, 'frontend/js/'), - '@modules': path.join(rootDir, 'modules/'), '@ol-types': path.join(rootDir, 'types/'), '@ol-storybook': path.join(rootDir, '.storybook/'), '@wf': path.join( diff --git a/services/web/scripts/backfill_library_references_search.mjs b/services/web/scripts/backfill_library_references_search.mjs index b381dae27e..8733c2163d 100644 --- a/services/web/scripts/backfill_library_references_search.mjs +++ b/services/web/scripts/backfill_library_references_search.mjs @@ -2,17 +2,13 @@ import minimist from 'minimist' import logger from '@overleaf/logger' import { db } from '../app/src/infrastructure/mongodb.mjs' -import { - buildSearchTokens, - docSchema, -} from '../modules/library/app/src/LibraryReferenceRepository.mts' -import { tokenize } from '../modules/library/app/src/bibtex-search-tokens.mts' +import { buildSearchFields } from '../modules/library/app/src/LibraryReferenceRepository.mts' import { scriptRunner } from './lib/ScriptRunner.mjs' /** @typedef {import('mongodb').AnyBulkWriteOperation} AnyBulkWriteOperation */ const argv = minimist(process.argv.slice(2), { - boolean: ['commit', 'all', 'help'], + boolean: ['commit', 'rollback', 'all', 'help'], default: { 'batch-size': 1000 }, }) @@ -21,15 +17,16 @@ function usage() { {}, `Usage: node backfill_library_references_search.mjs [options] -Populates searchKey and searchTokens on libraryReferences so the -account-level library search can index them. Also unsets the obsolete -fields.$[].searchValue. Safe to rerun; picks up only un-indexed rows -by default. +Populates searchKey and fields.searchValue on libraryReferences so the +account-level library search can index them. Safe to rerun; picks up only +un-indexed rows by default. Options: --commit Apply changes. Without this, runs as a dry run. - --all Re-index every row, not just rows where searchTokens - is null. Use when the tokenization format has changed. + --rollback Unset searchKey and fields.searchValue on all rows that + have them. Mirrors the original migration's rollback. + --all Re-index every row, not just rows where searchKey is null. + Use when the tokenization format has changed. --batch-size bulkWrite batch size (default 1000). ` ) @@ -44,10 +41,11 @@ const BATCH_SIZE = Number(argv['batch-size']) /** @param {(message: string) => Promise} trackProgress */ async function backfill(trackProgress) { - const filter = argv.all ? {} : { searchTokens: null } + const filter = argv.all ? {} : { searchKey: null } const cursor = db.libraryReferences .find(filter) - .project({ key: 1, type: 1, fields: 1, updatedAt: 1 }) + .hint({ userId: 1, searchKey: 1 }) + .project({ key: 1, fields: 1 }) let processed = 0 /** @type {AnyBulkWriteOperation[]} */ @@ -66,20 +64,19 @@ async function backfill(trackProgress) { } for await (const doc of cursor) { - const entry = docSchema.parse({ - ...doc, - type: doc.type ?? 'misc', - updatedAt: doc.updatedAt ?? new Date(0), + const { searchKey, fields } = buildSearchFields({ + key: doc.key, + fields: (doc.fields ?? []).map( + (/** @type {{ name: string; editableValue?: string }} */ f) => ({ + name: f.name, + editableValue: f.editableValue ?? '', + }) + ), }) - const searchKey = tokenize(doc.key) - const searchTokens = buildSearchTokens(entry) ops.push({ updateOne: { filter: { _id: doc._id }, - update: { - $set: { searchKey, searchTokens }, - $unset: { 'fields.$[].searchValue': 1 }, - }, + update: { $set: { searchKey, fields } }, }, }) if (ops.length >= BATCH_SIZE) { @@ -90,17 +87,39 @@ async function backfill(trackProgress) { await trackProgress(`done; processed ${processed} docs`) } +/** @param {(message: string) => Promise} trackProgress */ +async function rollback(trackProgress) { + if (!argv.commit) { + const count = await db.libraryReferences.countDocuments({ + searchKey: { $ne: null }, + }) + await trackProgress(`[dry-run] would unset search fields on ${count} docs`) + return + } + const result = await db.libraryReferences.updateMany( + { searchKey: { $ne: null } }, + { $unset: { searchKey: 1, 'fields.$[].searchValue': 1 } }, + { hint: { userId: 1, searchKey: 1 } } + ) + await trackProgress(`unset search fields on ${result.modifiedCount} docs`) +} + /** @param {(message: string) => Promise} trackProgress */ async function main(trackProgress) { if (!argv.commit) { await trackProgress('DRY RUN. Pass --commit to apply changes.') } - await backfill(trackProgress) + if (argv.rollback) { + await rollback(trackProgress) + } else { + await backfill(trackProgress) + } } try { await scriptRunner(main, { commit: Boolean(argv.commit), + rollback: Boolean(argv.rollback), all: Boolean(argv.all), batchSize: BATCH_SIZE, }) diff --git a/services/web/tsconfig.backend.json b/services/web/tsconfig.backend.json index 2207ee3d38..6549536bc8 100644 --- a/services/web/tsconfig.backend.json +++ b/services/web/tsconfig.backend.json @@ -6,7 +6,6 @@ "include": [ "app/src/**/*", "modules/*/app/src/**/*", - "modules/*/shared/**/*", "modules/*/test/acceptance/**/*", "modules/*/test/unit/**/*", "scripts/**/*", diff --git a/services/web/tsconfig.json b/services/web/tsconfig.json index 15dbc72f20..2e5fc9ad56 100644 --- a/services/web/tsconfig.json +++ b/services/web/tsconfig.json @@ -14,7 +14,6 @@ "forceConsistentCasingInFileNames": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "rewriteRelativeImportExtensions": true, "baseUrl": ".", "paths": { "@/*": ["./frontend/js/*"], @@ -39,7 +38,6 @@ "include": [ "frontend/js/**/*.*", "modules/**/frontend/js/**/*.*", - "modules/*/shared/**/*.*", "test/frontend/**/*.*", "modules/**/test/frontend/**/*.*", "frontend/stories/**/*.*", diff --git a/tools/migrations/20260612120000_replace_libraryReferences_searchTokens_index.mjs b/tools/migrations/20260612120000_replace_libraryReferences_searchTokens_index.mjs deleted file mode 100644 index c7e99643c9..0000000000 --- a/tools/migrations/20260612120000_replace_libraryReferences_searchTokens_index.mjs +++ /dev/null @@ -1,26 +0,0 @@ -import Helpers from './lib/helpers.mjs' - -const tags = ['saas'] - -const newIndexes = [ - { - key: { userId: 1, searchTokens: 1 }, - name: 'userId_1_searchTokens_1', - }, -] - -const migrate = async client => { - const { db } = client - await Helpers.addIndexesToCollection(db.libraryReferences, newIndexes) -} - -const rollback = async client => { - const { db } = client - await Helpers.dropIndexesFromCollection(db.libraryReferences, newIndexes) -} - -export default { - tags, - migrate, - rollback, -}