mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-23 14:12:11 -03:00
Add fuzzy search support to paginated data retrieval
This commit is contained in:
@@ -108,6 +108,7 @@ class ApiRoutes:
|
|||||||
sort_by = request.query.get('sort_by', 'name')
|
sort_by = request.query.get('sort_by', 'name')
|
||||||
folder = request.query.get('folder')
|
folder = request.query.get('folder')
|
||||||
search = request.query.get('search', '').lower()
|
search = request.query.get('search', '').lower()
|
||||||
|
fuzzy = request.query.get('fuzzy', 'false').lower() == 'true'
|
||||||
|
|
||||||
# Validate parameters
|
# Validate parameters
|
||||||
if page < 1 or page_size < 1 or page_size > 100:
|
if page < 1 or page_size < 1 or page_size > 100:
|
||||||
@@ -126,7 +127,8 @@ class ApiRoutes:
|
|||||||
page_size=page_size,
|
page_size=page_size,
|
||||||
sort_by=sort_by,
|
sort_by=sort_by,
|
||||||
folder=folder,
|
folder=folder,
|
||||||
search=search
|
search=search,
|
||||||
|
fuzzy=fuzzy
|
||||||
)
|
)
|
||||||
|
|
||||||
# Format the response data
|
# Format the response data
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from operator import itemgetter
|
|||||||
from ..config import config
|
from ..config import config
|
||||||
from ..utils.file_utils import load_metadata, get_file_info
|
from ..utils.file_utils import load_metadata, get_file_info
|
||||||
from .lora_cache import LoraCache
|
from .lora_cache import LoraCache
|
||||||
|
from difflib import SequenceMatcher
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -91,36 +92,81 @@ class LoraScanner:
|
|||||||
# Call resort_cache to create sorted views
|
# Call resort_cache to create sorted views
|
||||||
await self._cache.resort()
|
await self._cache.resort()
|
||||||
|
|
||||||
async def get_paginated_data(self,
|
def fuzzy_match(self, text: str, pattern: str, threshold: float = 0.7) -> bool:
|
||||||
page: int,
|
"""
|
||||||
page_size: int,
|
Check if text matches pattern using fuzzy matching.
|
||||||
sort_by: str = 'date',
|
Returns True if similarity ratio is above threshold.
|
||||||
folder: Optional[str] = None,
|
"""
|
||||||
search: Optional[str] = None) -> Dict:
|
if not pattern or not text:
|
||||||
"""Get paginated LoRA data with search support"""
|
return False
|
||||||
|
|
||||||
|
# Convert both to lowercase for case-insensitive matching
|
||||||
|
text = text.lower()
|
||||||
|
pattern = pattern.lower()
|
||||||
|
|
||||||
|
# Split pattern into words
|
||||||
|
search_words = pattern.split()
|
||||||
|
|
||||||
|
# Check each word
|
||||||
|
for word in search_words:
|
||||||
|
# First check if word is a substring (faster)
|
||||||
|
if word in text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If not found as substring, try fuzzy matching
|
||||||
|
# Check if any part of the text matches this word
|
||||||
|
found_match = False
|
||||||
|
for text_part in text.split():
|
||||||
|
ratio = SequenceMatcher(None, text_part, word).ratio()
|
||||||
|
if ratio >= threshold:
|
||||||
|
found_match = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found_match:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# All words found either as substrings or fuzzy matches
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'name',
|
||||||
|
folder: str = None, search: str = None, fuzzy: bool = False):
|
||||||
cache = await self.get_cached_data()
|
cache = await self.get_cached_data()
|
||||||
|
|
||||||
# 先获取基础数据集
|
# 先获取基础数据集
|
||||||
data = cache.sorted_by_date if sort_by == 'date' else cache.sorted_by_name
|
filtered_data = cache.sorted_by_date if sort_by == 'date' else cache.sorted_by_name
|
||||||
|
|
||||||
# 应用文件夹过滤
|
# 应用文件夹过滤
|
||||||
if folder is not None:
|
if folder is not None:
|
||||||
data = [item for item in data if item['folder'] == folder]
|
filtered_data = [item for item in filtered_data if item['folder'] == folder]
|
||||||
|
|
||||||
# 应用搜索过滤(只匹配model_name)
|
# 应用搜索过滤(只匹配model_name)
|
||||||
if search:
|
if search:
|
||||||
search = search.lower().strip()
|
if fuzzy:
|
||||||
before_search = len(data)
|
filtered_data = [
|
||||||
data = [item for item in data
|
item for item in filtered_data
|
||||||
if search in item['model_name'].lower()]
|
if any(
|
||||||
|
self.fuzzy_match(str(value), search)
|
||||||
|
for value in [
|
||||||
|
item.get('model_name', ''),
|
||||||
|
item.get('base_model', '')
|
||||||
|
]
|
||||||
|
if value
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# Original exact search logic
|
||||||
|
filtered_data = [
|
||||||
|
item for item in filtered_data
|
||||||
|
if search in str(item.get('model_name', '')).lower()
|
||||||
|
]
|
||||||
|
|
||||||
# 计算分页
|
# 计算分页
|
||||||
total_items = len(data)
|
total_items = len(filtered_data)
|
||||||
start_idx = (page - 1) * page_size
|
start_idx = (page - 1) * page_size
|
||||||
end_idx = min(start_idx + page_size, total_items)
|
end_idx = min(start_idx + page_size, total_items)
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'items': data[start_idx:end_idx],
|
'items': filtered_data[start_idx:end_idx],
|
||||||
'total': total_items,
|
'total': total_items,
|
||||||
'page': page,
|
'page': page,
|
||||||
'page_size': page_size,
|
'page_size': page_size,
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export class SearchManager {
|
|||||||
url.searchParams.set('page_size', '20');
|
url.searchParams.set('page_size', '20');
|
||||||
url.searchParams.set('sort_by', state.sortBy);
|
url.searchParams.set('sort_by', state.sortBy);
|
||||||
url.searchParams.set('search', searchTerm);
|
url.searchParams.set('search', searchTerm);
|
||||||
|
url.searchParams.set('fuzzy', 'true');
|
||||||
|
|
||||||
if (state.activeFolder) {
|
if (state.activeFolder) {
|
||||||
url.searchParams.set('folder', state.activeFolder);
|
url.searchParams.set('folder', state.activeFolder);
|
||||||
|
|||||||
Reference in New Issue
Block a user