Skip to content

Commit 1ed686b

Browse files
committed
use weighting system
1 parent ec08457 commit 1ed686b

File tree

2 files changed

+34
-35
lines changed

2 files changed

+34
-35
lines changed

packages/site-kit/src/lib/search/search.ts

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -44,73 +44,71 @@ export function init(blocks: Block[]) {
4444
inited = true;
4545
}
4646

47+
const CURRENT_SECTION_BOOST = 2;
48+
const EXACT_MATCH_BOOST = 10;
49+
const WORD_MATCH_BOOST = 4;
50+
const NEAR_MATCH_BOOST = 2;
51+
const BREADCRUMB_LENGTH_BOOST = 0.2;
52+
4753
/**
4854
* Search for a given query in the existing index
4955
*/
5056
export function search(query: string, path: string): BlockGroup[] {
5157
const escaped = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
52-
const regex = new RegExp(`(^|\\b)${escaped}`, 'i');
58+
const exact_match = new RegExp(`^${escaped}$`, 'i');
59+
const word_match = new RegExp(`(^|\\b)${escaped}($|\\b)`, 'i');
60+
const near_match = new RegExp(`(^|\\b)${escaped}`, 'i');
5361

5462
const parts = path.split('/');
5563

5664
const blocks = indexes
5765
.flatMap((index) => index.search(query))
5866
// @ts-expect-error flexsearch types are wrong i think?
5967
.map(lookup)
60-
.map((block, rank) => ({ block: block as Block, rank }))
61-
.sort((a, b) => {
68+
.map((block) => {
69+
const block_parts = block.href.split('/');
70+
6271
// prioritise current section
63-
const a_parts = a.block.href.split('/');
64-
const b_parts = b.block.href.split('/');
65-
66-
for (let i = 0; i < parts.length; i += 1) {
67-
const a_part_matches = a_parts[i] === parts[i];
68-
const b_part_matches = b_parts[i] === parts[i];
69-
70-
if (!a_part_matches || !b_part_matches) {
71-
if (a_part_matches !== b_part_matches) {
72-
if (i > 1) {
73-
console.log('here', a, b);
74-
}
75-
return a_part_matches ? -1 : 1;
76-
}
77-
78-
break;
79-
}
72+
let score = block_parts.findIndex((part, i) => part !== parts[i]);
73+
if (score === -1) score = block_parts.length;
74+
score *= CURRENT_SECTION_BOOST;
75+
76+
if (block.breadcrumbs.some((text) => exact_match.test(text))) {
77+
console.log('EXACT MATCH', block.breadcrumbs);
78+
score += EXACT_MATCH_BOOST;
79+
} else if (block.breadcrumbs.some((text) => word_match.test(text))) {
80+
score += WORD_MATCH_BOOST;
81+
} else if (block.breadcrumbs.some((text) => near_match.test(text))) {
82+
score += NEAR_MATCH_BOOST;
8083
}
8184

82-
const a_title_matches = regex.test(a.block.breadcrumbs.at(-1)!);
83-
const b_title_matches = regex.test(b.block.breadcrumbs.at(-1)!);
84-
85-
// massage the order a bit, so that title matches
86-
// are given higher priority
87-
if (a_title_matches !== b_title_matches) {
88-
return a_title_matches ? -1 : 1;
89-
}
85+
// prioritise branches over leaves
86+
score -= block.breadcrumbs.length * BREADCRUMB_LENGTH_BOOST;
9087

91-
return a.block.breadcrumbs.length - b.block.breadcrumbs.length || a.rank - b.rank;
92-
})
93-
.map(({ block }) => block);
88+
return { block, score };
89+
});
9490

9591
const groups: Record<string, BlockGroup> = {};
9692

97-
for (const block of blocks) {
93+
for (const { score, block } of blocks) {
9894
const breadcrumbs = block.breadcrumbs.slice(0, 2);
9995

10096
const group = (groups[breadcrumbs.join('::')] ??= {
10197
breadcrumbs,
102-
blocks: []
98+
blocks: [],
99+
score: 0
103100
});
104101

102+
group.score = Math.max(score, group.score);
105103
group.blocks.push(block);
106104
}
107105

108-
return Object.values(groups);
106+
return Object.values(groups).sort((a, b) => b.score - a.score);
109107
}
110108

111109
/**
112110
* Get a block with details by its href
113111
*/
114112
export function lookup(href: string) {
115-
return map.get(href);
113+
return map.get(href)!;
116114
}

packages/site-kit/src/lib/search/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export interface Block {
88
export interface BlockGroup {
99
breadcrumbs: string[];
1010
blocks: Block[];
11+
score: number;
1112
}

0 commit comments

Comments
 (0)