Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions server/search/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,43 @@ export const getSearchUsers = async (searchString: string, limit = 5) => {
limit,
});
};

/**
* Batch-search for multiple author names in a single query, returning a map
* from each searched name to its matching users (up to `limit` per name).
*/
export const batchSearchUsers = async (names: string[], limit = 5) => {
const nonEmpty = names.filter((n) => n.length > 0);
if (nonEmpty.length === 0) {
return new Map<string, any[]>();
}

const users = await User.findAll({
where: {
[Op.or]: nonEmpty.flatMap((name) => [
{ fullName: { [Op.iLike]: `%${name}%` } },
{ slug: { [Op.iLike]: `%${name}%` } },
{ email: { [Op.iLike]: name } },
]),
},
attributes: ['id', 'slug', 'fullName', 'initials', 'avatar'],
});

const resultMap = new Map<string, any[]>(nonEmpty.map((name) => [name, []]));
const allUsers = users.map((u) => u.toJSON());

for (const name of nonEmpty) {
const lowerName = name.toLowerCase();
const matches = allUsers
.filter(
(u: any) =>
u.fullName?.toLowerCase().includes(lowerName) ||
u.slug?.toLowerCase().includes(lowerName) ||
u.email?.toLowerCase() === lowerName,
)
.slice(0, limit);
resultMap.set(name, matches);
}

return resultMap;
};
1 change: 1 addition & 0 deletions workers/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ let currentWorkerThreads = 0;
/** Nice to be able to run certain tasks longer than the default timeout */
const customTimeouts = {
archive: 14_400, // 4 hours
import: 300, // 5 minutes
} satisfies Partial<Record<TaskType, number>>;

if (env.NODE_ENV === 'production') {
Expand Down
22 changes: 13 additions & 9 deletions workers/tasks/import/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Falsy } from 'types';
import { metaValueToJsonSerializable, metaValueToString } from '@pubpub/prosemirror-pandoc';
import unidecode from 'unidecode';

import { getSearchUsers } from 'server/search/queries';
import { batchSearchUsers } from 'server/search/queries';
import { isValidDate } from 'utils/dates';

const getAuthorsArray = (author) => {
Expand All @@ -28,15 +28,19 @@ const getAttributions = async (author) => {
if (author) {
const authorsArray = getAuthorsArray(author);
const authorEntries = authorsArray.map(metaValueToJsonSerializable) as any[];
const attributions = await Promise.all(
authorEntries.map(async (authorEntry: string) => {
if (typeof authorEntry === 'string') {
const users = await getSearchUsers(authorEntry);
return { name: authorEntry, users: users.map((user) => user.toJSON()) };
}
return authorEntry;
}),
const stringEntries = authorEntries.filter(
(entry): entry is string => typeof entry === 'string',
);
const usersByName =
stringEntries.length > 0
? await batchSearchUsers(stringEntries)
: new Map<string, any[]>();
const attributions = authorEntries.map((authorEntry) => {
if (typeof authorEntry === 'string') {
return { name: authorEntry, users: usersByName.get(authorEntry) ?? [] };
}
return authorEntry;
});
return attributions;
}
return null;
Expand Down
Loading