fix: highlight full knowledge search terms
This commit is contained in:
@@ -657,6 +657,9 @@ def _merge_content_search_rows(rows, keyword: str, chunk_section_ids: set[int])
|
||||
for matched in _matched_in(str(row["title"] or ""), str(row["content"] or ""), keyword):
|
||||
if matched not in current["matchedIn"]:
|
||||
current["matchedIn"].append(matched)
|
||||
for term in _highlight_terms(str(row["title"] or ""), str(row["content"] or ""), keyword):
|
||||
if term not in current["highlightTerms"]:
|
||||
current["highlightTerms"].append(term)
|
||||
current["itemType"] = _primary_item_type(current["itemTypes"])
|
||||
return list(grouped.values())
|
||||
|
||||
@@ -688,6 +691,7 @@ def _content_search_item(row, keyword: str, has_chunks: bool) -> dict:
|
||||
"title": title,
|
||||
"snippet": _snippet(f"{title}\n{content}", keyword),
|
||||
"matchedIn": _matched_in(title, content, keyword),
|
||||
"highlightTerms": _highlight_terms(title, content, keyword),
|
||||
"itemTypes": [row["item_type"]],
|
||||
"hasChunks": has_chunks,
|
||||
"isCurrentVersion": True,
|
||||
@@ -712,6 +716,28 @@ def _matched_in(title: str, content: str, keyword: str) -> list[str]:
|
||||
return result or ["content"]
|
||||
|
||||
|
||||
def _highlight_terms(title: str, content: str, keyword: str) -> list[str]:
|
||||
keyword = keyword.strip()
|
||||
if not keyword:
|
||||
return []
|
||||
text = f"{title}\n{content}".lower()
|
||||
terms = [keyword]
|
||||
if keyword.lower() not in text:
|
||||
terms.extend(_keyword_parts(keyword))
|
||||
result: list[str] = []
|
||||
for term in sorted({item.strip() for item in terms if item.strip()}, key=len, reverse=True):
|
||||
if term.lower() in text and term not in result:
|
||||
result.append(term)
|
||||
return result or [keyword]
|
||||
|
||||
|
||||
def _keyword_parts(keyword: str) -> list[str]:
|
||||
parts = [part for part in keyword.replace(",", " ").replace(",", " ").split() if part]
|
||||
if parts:
|
||||
return parts
|
||||
return list(keyword) if len(keyword) <= 8 else []
|
||||
|
||||
|
||||
def _snippet(text: str, keyword: str, radius: int = 90) -> str:
|
||||
compact = " ".join(text.split())
|
||||
if not compact:
|
||||
|
||||
@@ -359,3 +359,25 @@ def test_content_search_can_exclude_closed_knowledge():
|
||||
assert included["data"]["total"] == 1
|
||||
assert included["data"]["items"][0]["canAgentUse"] is False
|
||||
assert excluded["data"]["total"] == 0
|
||||
|
||||
|
||||
def test_content_search_highlight_terms_keep_full_keyword():
|
||||
with _database() as db:
|
||||
item = _knowledge(db)
|
||||
db.add(KnowledgeSection(
|
||||
knowledge_id=item.id,
|
||||
version_id=item.current_version_id,
|
||||
section_key="S0002",
|
||||
title="能力心密钥",
|
||||
content="能力心钥用于说明能力心的核心方向。",
|
||||
source_start=0,
|
||||
source_end=10,
|
||||
sort_order=1,
|
||||
content_hash="highlight-section",
|
||||
))
|
||||
db.commit()
|
||||
|
||||
response = content_search("心钥", includeClosed=True, page=1, pageSize=10, db=db, current_admin=_admin())
|
||||
|
||||
assert response["data"]["total"] == 1
|
||||
assert response["data"]["items"][0]["highlightTerms"][0] == "心钥"
|
||||
|
||||
Reference in New Issue
Block a user