дедупликация
Tests / frontend-test (push) Successful in 1m9s

This commit is contained in:
gorbenko.pavel
2026-08-11 14:24:32 +05:00
parent 850249eaef
commit 3d52634677
@@ -539,11 +539,20 @@ function freeTextClause(query: string): string | undefined {
}
// Ответ Search → пары (Id элемента, его тип по префиксу Path).
//
// Дедуп по (тип, Id) — ЗДЕСЬ, а не у вызывающей стороны: во всех запросах
// стоит TrimDuplicates: false (нужно, чтобы найти черновики и «свои» копии —
// стандартная дедупликация Search иногда схлопывает и их), а без неё индекс
// может вернуть один и тот же элемент несколькими хитами (переиндексация,
// несколько «версий» в crawl). Раньше хиты превращались в строки один-в-один,
// и дубликат из индекса становился дубликатом строки в таблице — с одинаковым
// React-ключом, то есть видимым «залипанием» одной и той же заявки дважды.
function hitsToEntries(
results: { PrimarySearchResults: unknown[] },
types: IRequestType[]
): Array<{ id: number; type: IRequestType }> {
const urls = types.map((t) => ({ type: t, url: listAbsUrl(t).toLowerCase() }));
const seen = new Set<string>();
return (results.PrimarySearchResults as Array<Record<string, unknown>>)
.map((r) => ({ id: Number(r.ListItemID), path: String(r.Path || '').toLowerCase() }))
.filter((h) => !isNaN(h.id) && h.id > 0)
@@ -551,7 +560,13 @@ function hitsToEntries(
const matched = urls.filter((u) => h.path.indexOf(u.url) === 0)[0];
return matched ? { id: h.id, type: matched.type } : undefined;
})
.filter((e): e is { id: number; type: IRequestType } => !!e);
.filter((e): e is { id: number; type: IRequestType } => !!e)
.filter((e) => {
const key = `${e.type.id}-${e.id}`;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
// Дочитать поля заявок по найденным Id (Search отдаёт не все колонки, и для