diff --git a/frontend/src/components/RedisViewer.interaction.test.tsx b/frontend/src/components/RedisViewer.interaction.test.tsx index db2d73eb..3d7b248b 100644 --- a/frontend/src/components/RedisViewer.interaction.test.tsx +++ b/frontend/src/components/RedisViewer.interaction.test.tsx @@ -336,10 +336,10 @@ describe('RedisViewer tree interactions', () => { expect(event.preventDefault).toHaveBeenCalled(); expect(event.stopPropagation).toHaveBeenCalled(); expect(searchInput?.props.value).toBe('app:user'); - expect(updatedSearchModeGroup.props.value).toBe('fuzzy'); + expect(updatedSearchModeGroup.props.value).toBe('prefix'); expect(redisBackend.RedisScanKeys).toHaveBeenLastCalledWith( expect.any(Object), - '*[aA][pP][pP]:[uU][sS][eE][rR]*', + '[aA][pP][pP]:[uU][sS][eE][rR]*', '0', 600, ); diff --git a/frontend/src/components/RedisViewer.tsx b/frontend/src/components/RedisViewer.tsx index 428650e8..68c62288 100644 --- a/frontend/src/components/RedisViewer.tsx +++ b/frontend/src/components/RedisViewer.tsx @@ -255,7 +255,7 @@ const RedisViewer: React.FC = ({ connectionId, redisDB }) => { const [loading, setLoading] = useState(false); const [searchInput, setSearchInput] = useState(''); const [searchPattern, setSearchPattern] = useState('*'); - const [searchMode, setSearchMode] = useState('fuzzy'); + const [searchMode, setSearchMode] = useState('prefix'); const [cursor, setCursor] = useState('0'); const [hasMore, setHasMore] = useState(false); const [loadingAllKeys, setLoadingAllKeys] = useState(false); @@ -1098,8 +1098,8 @@ const RedisViewer: React.FC = ({ connectionId, redisDB }) => { return; } - setSearchMode('fuzzy'); - executeSearch(groupPath, 'fuzzy'); + setSearchMode('prefix'); + executeSearch(groupPath, 'prefix'); }, [executeSearch]); const stopTreeTitleEvent = (event: React.SyntheticEvent) => { @@ -2279,13 +2279,13 @@ const RedisViewer: React.FC = ({ connectionId, redisDB }) => { buttonStyle="solid" style={{ flexShrink: 0 }} > - {tr('redis_viewer.search.fuzzy')} + {tr('redis_viewer.search.prefix')} {tr('redis_viewer.search.exact')} = ({ buttonStyle="solid" style={{ flexShrink: 0 }} > - {tr('redis_viewer.search.fuzzy')} + {tr('redis_viewer.search.prefix')} {tr('redis_viewer.search.exact')} { }); }); - it('wraps plain keywords with wildcard for contains matching', () => { + it('adds only a trailing wildcard for prefix matching', () => { expect(normalizeRedisSearchInput('order')).toEqual({ keyword: 'order', - pattern: '*[oO][rR][dD][eE][rR]*', + pattern: '[oO][rR][dD][eE][rR]*', }); }); it('builds ascii case-insensitive patterns for letter keywords', () => { expect(normalizeRedisSearchInput('agent')).toEqual({ keyword: 'agent', - pattern: '*[aA][gG][eE][nN][tT]*', + pattern: '[aA][gG][eE][nN][tT]*', }); }); it('escapes redis glob special characters as literals', () => { expect(normalizeRedisSearchInput('user:*:[id]?')).toEqual({ keyword: 'user:*:[id]?', - pattern: '*[uU][sS][eE][rR]:\\*:\\[[iI][dD]\\]\\?*', + pattern: '[uU][sS][eE][rR]:\\*:\\[[iI][dD]\\]\\?*', }); }); diff --git a/frontend/src/utils/redisSearchPattern.ts b/frontend/src/utils/redisSearchPattern.ts index cd110c65..69938bbd 100644 --- a/frontend/src/utils/redisSearchPattern.ts +++ b/frontend/src/utils/redisSearchPattern.ts @@ -1,7 +1,7 @@ const REDIS_GLOB_SPECIAL_CHARS = /([*?\[\]\\])/g; const ASCII_LETTER = /^[A-Za-z]$/; -export type RedisSearchMode = 'fuzzy' | 'exact'; +export type RedisSearchMode = 'prefix' | 'exact'; const escapeRedisGlobLiteral = (value: string): string => { return value.replace(REDIS_GLOB_SPECIAL_CHARS, '\\$1'); @@ -21,7 +21,7 @@ const toCaseInsensitiveRedisGlobLiteral = (value: string): string => { export const normalizeRedisSearchInput = ( rawValue: string, - mode: RedisSearchMode = 'fuzzy', + mode: RedisSearchMode = 'prefix', ): { keyword: string; pattern: string } => { const keyword = String(rawValue || '').trim(); if (!keyword) { @@ -35,11 +35,11 @@ export const normalizeRedisSearchInput = ( } return { keyword, - pattern: `*${toCaseInsensitiveRedisGlobLiteral(keyword)}*`, + pattern: `${toCaseInsensitiveRedisGlobLiteral(keyword)}*`, }; }; -export const normalizeRedisSearchDraftChange = (rawValue: string, mode: RedisSearchMode = 'fuzzy'): { +export const normalizeRedisSearchDraftChange = (rawValue: string, mode: RedisSearchMode = 'prefix'): { keyword: string; pattern: string; shouldSearchImmediately: boolean; diff --git a/shared/i18n/de-DE.json b/shared/i18n/de-DE.json index 99263f60..84da97fb 100644 --- a/shared/i18n/de-DE.json +++ b/shared/i18n/de-DE.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "Neuen Mitgliedswert eingeben", "redis_viewer.placeholder.search_exact": "Vollständigen Key oder Namespace für exakte Suche eingeben", - "redis_viewer.placeholder.search_fuzzy": "Keys suchen (unscharfe Suche)", + "redis_viewer.placeholder.search_prefix": "Keys nach Präfix suchen", "redis_viewer.placeholder.stream_id": "Zum Beispiel: * oder 1723110000000-0", "redis_viewer.placeholder.value": "Wert", "redis_viewer.search.exact": "Exakt", - "redis_viewer.search.fuzzy": "Unscharf", + "redis_viewer.search.prefix": "Präfix", "redis_viewer.state.connection_not_found": "Verbindung nicht gefunden", "redis_viewer.state.empty_selection": "Wählen Sie einen Key aus, um Details anzuzeigen", "redis_viewer.state.import_preview_empty": "Wählen Sie eine Redis-Exportdatei aus, prüfen Sie die Vorschau und wählen Sie die zu importierenden Keys aus", diff --git a/shared/i18n/en-US.json b/shared/i18n/en-US.json index 281162b3..4d623d75 100644 --- a/shared/i18n/en-US.json +++ b/shared/i18n/en-US.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "Enter new member value", "redis_viewer.placeholder.search_exact": "Enter full Key or namespace for exact search", - "redis_viewer.placeholder.search_fuzzy": "Search Keys (fuzzy match)", + "redis_viewer.placeholder.search_prefix": "Search Keys by prefix", "redis_viewer.placeholder.stream_id": "For example: * or 1723110000000-0", "redis_viewer.placeholder.value": "Value", "redis_viewer.search.exact": "Exact", - "redis_viewer.search.fuzzy": "Fuzzy", + "redis_viewer.search.prefix": "Prefix", "redis_viewer.state.connection_not_found": "Connection not found", "redis_viewer.state.empty_selection": "Select a Key to view details", "redis_viewer.state.import_preview_empty": "Select a Redis export file to preview and choose Keys to import", diff --git a/shared/i18n/ja-JP.json b/shared/i18n/ja-JP.json index d99014d5..1f16080e 100644 --- a/shared/i18n/ja-JP.json +++ b/shared/i18n/ja-JP.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "新しいメンバー値を入力", "redis_viewer.placeholder.search_exact": "完全一致検索する Key または名前空間を入力", - "redis_viewer.placeholder.search_fuzzy": "Key を検索(あいまい一致)", + "redis_viewer.placeholder.search_prefix": "Key を前方一致で検索", "redis_viewer.placeholder.stream_id": "例: * または 1723110000000-0", "redis_viewer.placeholder.value": "値", "redis_viewer.search.exact": "完全一致", - "redis_viewer.search.fuzzy": "あいまい", + "redis_viewer.search.prefix": "前方一致", "redis_viewer.state.connection_not_found": "接続が見つかりません", "redis_viewer.state.empty_selection": "詳細を表示する Key を選択してください", "redis_viewer.state.import_preview_empty": "Redis エクスポートファイルを選択し、プレビューしてインポートする Key を選択してください", diff --git a/shared/i18n/ru-RU.json b/shared/i18n/ru-RU.json index dfc1f890..484a4899 100644 --- a/shared/i18n/ru-RU.json +++ b/shared/i18n/ru-RU.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "Введите значение нового участника", "redis_viewer.placeholder.search_exact": "Введите полный Key или namespace для точного поиска", - "redis_viewer.placeholder.search_fuzzy": "Поиск Keys (нечеткое совпадение)", + "redis_viewer.placeholder.search_prefix": "Поиск Keys по префиксу", "redis_viewer.placeholder.stream_id": "Например: * или 1723110000000-0", "redis_viewer.placeholder.value": "Значение", "redis_viewer.search.exact": "Точно", - "redis_viewer.search.fuzzy": "Нечетко", + "redis_viewer.search.prefix": "Префикс", "redis_viewer.state.connection_not_found": "Подключение не найдено", "redis_viewer.state.empty_selection": "Выберите Key, чтобы просмотреть детали", "redis_viewer.state.import_preview_empty": "Выберите файл экспорта Redis, просмотрите его и отметьте Keys для импорта", diff --git a/shared/i18n/zh-CN.json b/shared/i18n/zh-CN.json index a7cc44ac..0e867061 100644 --- a/shared/i18n/zh-CN.json +++ b/shared/i18n/zh-CN.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "输入新成员值", "redis_viewer.placeholder.search_exact": "输入完整 Key 或命名空间进行精确搜索", - "redis_viewer.placeholder.search_fuzzy": "搜索 Key(模糊匹配)", + "redis_viewer.placeholder.search_prefix": "按前缀搜索 Key", "redis_viewer.placeholder.stream_id": "例如:* 或 1723110000000-0", "redis_viewer.placeholder.value": "值", "redis_viewer.search.exact": "精确", - "redis_viewer.search.fuzzy": "模糊", + "redis_viewer.search.prefix": "前缀", "redis_viewer.state.connection_not_found": "未找到连接", "redis_viewer.state.empty_selection": "选择一个 Key 查看详情", "redis_viewer.state.import_preview_empty": "请选择 Redis 导出文件,预览后勾选要导入的 Key", diff --git a/shared/i18n/zh-TW.json b/shared/i18n/zh-TW.json index 4cb1d23c..ac2d63b5 100644 --- a/shared/i18n/zh-TW.json +++ b/shared/i18n/zh-TW.json @@ -6972,11 +6972,11 @@ "redis_viewer.placeholder.new_key_name": "new:key:name", "redis_viewer.placeholder.new_member_value": "輸入新成員值", "redis_viewer.placeholder.search_exact": "輸入完整 Key 或命名空間進行精確搜尋", - "redis_viewer.placeholder.search_fuzzy": "搜尋 Key(模糊比對)", + "redis_viewer.placeholder.search_prefix": "依前綴搜尋 Key", "redis_viewer.placeholder.stream_id": "例如:* 或 1723110000000-0", "redis_viewer.placeholder.value": "值", "redis_viewer.search.exact": "精確", - "redis_viewer.search.fuzzy": "模糊", + "redis_viewer.search.prefix": "前綴", "redis_viewer.state.connection_not_found": "找不到連線", "redis_viewer.state.empty_selection": "選取一個 Key 以查看詳細資料", "redis_viewer.state.import_preview_empty": "請選擇 Redis 匯出檔案,預覽後勾選要匯入的 Key",