mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Improve search accuracy in the app (instructions, examples, objects, tags) (#4906)
* Use tokenized search to improve search with multiple words looking into multiple keys (ex: name & description)
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
tuneMatches,
|
||||
type SearchResult,
|
||||
sharedFuseConfiguration,
|
||||
getFuseSearchQueryForMultipleKeys,
|
||||
} from '../../../UI/Search/UseSearchStructuredItem';
|
||||
const gd: libGDevelop = global.gd;
|
||||
|
||||
@@ -107,17 +108,19 @@ export default class InstructionOrExpressionSelector<
|
||||
} = this.props;
|
||||
const { searchText } = this.state;
|
||||
|
||||
const extendSearchText = `'${searchText
|
||||
.trim()
|
||||
.split(' ')
|
||||
.join(" '")}`;
|
||||
|
||||
const displayedInstructionsList: Array<SearchResult<T>> =
|
||||
!!extendSearchText && this.searchApi
|
||||
? this.searchApi.search(extendSearchText).map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
!!searchText && this.searchApi
|
||||
? this.searchApi
|
||||
.search(
|
||||
getFuseSearchQueryForMultipleKeys(searchText, [
|
||||
'displayedName',
|
||||
'fullGroupName',
|
||||
])
|
||||
)
|
||||
.map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
: [];
|
||||
const hasResults = !searchText || !!displayedInstructionsList.length;
|
||||
|
||||
|
@@ -55,6 +55,8 @@ import {
|
||||
type SearchResult,
|
||||
tuneMatches,
|
||||
sharedFuseConfiguration,
|
||||
getFuseSearchQueryForSimpleArray,
|
||||
getFuseSearchQueryForMultipleKeys,
|
||||
} from '../../UI/Search/UseSearchStructuredItem';
|
||||
import { Column, Line } from '../../UI/Grid';
|
||||
|
||||
@@ -193,33 +195,37 @@ export default class InstructionOrObjectSelector extends React.PureComponent<
|
||||
_search = (searchText: string) => {
|
||||
if (searchText === '') return;
|
||||
|
||||
const extendSearchText = `'${searchText
|
||||
.trim()
|
||||
.split(' ')
|
||||
.join(" '")}`;
|
||||
const extendedSearchText = getFuseSearchQueryForSimpleArray(searchText);
|
||||
|
||||
this.setState({
|
||||
searchResults: {
|
||||
objects: this.objectSearchApi
|
||||
? this.objectSearchApi.search(extendSearchText).map(result => ({
|
||||
? this.objectSearchApi.search(extendedSearchText).map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
: [],
|
||||
groups: this.groupSearchApi
|
||||
? this.groupSearchApi.search(extendSearchText).map(result => ({
|
||||
? this.groupSearchApi.search(extendedSearchText).map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
: [],
|
||||
instructions: this.instructionSearchApi
|
||||
? this.instructionSearchApi.search(extendSearchText).map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
? this.instructionSearchApi
|
||||
.search(
|
||||
getFuseSearchQueryForMultipleKeys(searchText, [
|
||||
'displayedName',
|
||||
'fullGroupName',
|
||||
])
|
||||
)
|
||||
.map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
: [],
|
||||
tags: this.tagSearchApi
|
||||
? this.tagSearchApi.search(extendSearchText).map(result => ({
|
||||
? this.tagSearchApi.search(extendedSearchText).map(result => ({
|
||||
item: result.item,
|
||||
matches: tuneMatches(result, searchText),
|
||||
}))
|
||||
|
@@ -730,13 +730,13 @@ const ObjectsList = React.forwardRef<Props, ObjectsListInterface>(
|
||||
{
|
||||
label: i18n._(t`Tags`),
|
||||
submenu: buildTagsMenuTemplate({
|
||||
noTagLabel: 'No tags',
|
||||
noTagLabel: i18n._(t`No tags`),
|
||||
getAllTags: getAllObjectTags,
|
||||
selectedTags: getTagsFromString(object.getTags()),
|
||||
onChange: objectTags => {
|
||||
changeObjectTags(object, objectTags);
|
||||
},
|
||||
editTagsLabel: 'Add/edit tags...',
|
||||
editTagsLabel: i18n._(t`Add/edit tags...`),
|
||||
onEditTags: () => openEditTagDialog(object),
|
||||
}),
|
||||
},
|
||||
|
@@ -30,6 +30,43 @@ export const sharedFuseConfiguration = {
|
||||
includeMatches: true,
|
||||
ignoreLocation: true,
|
||||
useExtendedSearch: true,
|
||||
findAllMatches: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* This helper allows creating the search query for a search within a simple array of strings.
|
||||
*/
|
||||
export const getFuseSearchQueryForSimpleArray = (searchText: string) => {
|
||||
const tokenisedSearchQuery = searchText.trim().split(' ');
|
||||
return `'${tokenisedSearchQuery.join(" '")}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* This helper allows creating the search query for searching within an array of
|
||||
* objects with multiple keys.
|
||||
* If we don't use this, the search will only be done on one of the keys.
|
||||
* See https://github.com/krisk/Fuse/issues/235#issuecomment-850269634
|
||||
*/
|
||||
export const getFuseSearchQueryForMultipleKeys = (
|
||||
searchText: string,
|
||||
keys: Array<string>
|
||||
) => {
|
||||
const tokenisedSearchQuery = searchText.trim().split(' ');
|
||||
const searchQuery: {
|
||||
$or: Fuse.Expression[],
|
||||
}[] = tokenisedSearchQuery.map((searchToken: string) => {
|
||||
const orFields: Fuse.Expression[] = keys.map(key => ({
|
||||
[key]: searchToken,
|
||||
}));
|
||||
|
||||
return {
|
||||
$or: orFields,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
$and: searchQuery,
|
||||
};
|
||||
};
|
||||
|
||||
const tuneMatchIndices = (match: SearchMatch, searchText: string) => {
|
||||
@@ -213,6 +250,7 @@ export const useSearchStructuredItem = <
|
||||
includeMatches: true,
|
||||
ignoreLocation: true,
|
||||
useExtendedSearch: true,
|
||||
findAllMatches: true,
|
||||
});
|
||||
|
||||
const totalTime = performance.now() - startTime;
|
||||
@@ -253,13 +291,15 @@ export const useSearchStructuredItem = <
|
||||
return;
|
||||
}
|
||||
|
||||
const extendSearchText = `'${searchText
|
||||
.trim()
|
||||
.split(' ')
|
||||
.join(" '")}`;
|
||||
|
||||
const startTime = performance.now();
|
||||
const results = searchApi.search(extendSearchText);
|
||||
const results = searchApi.search(
|
||||
getFuseSearchQueryForMultipleKeys(searchText, [
|
||||
'name',
|
||||
'fullName',
|
||||
'shortDescription',
|
||||
'tags',
|
||||
])
|
||||
);
|
||||
const totalTime = performance.now() - startTime;
|
||||
console.info(
|
||||
`Found ${results.length} items in ${totalTime.toFixed(3)}ms.`
|
||||
|
Reference in New Issue
Block a user