fix: D2 中文搜索 + D3 混合布尔语义 — PubMed 搜索路径修复
D2: PubMed 路径搜索中文(不带字段标签)时,plainto_tsquery("english")
对中文返回空,导致零结果。新增 ILIKE fallback 检测中文字符。
D3: A OR B AND C 被解析器拉平为 A OR B OR C。修改 _parse_or_expr
保留 AND cluster 分组,引擎正确产生产出 A OR (B AND C)。
This commit is contained in:
@@ -473,15 +473,36 @@ class PubmedQueryParser:
|
||||
result.plain_terms.append(term)
|
||||
|
||||
def _parse_or_expr(self, result: ParsedPubmedQuery) -> list[Term]:
|
||||
"""or_expr → and_expr (OR and_expr)*"""
|
||||
left = self._parse_and_expr(result)
|
||||
"""or_expr → and_expr (OR and_expr)*
|
||||
|
||||
P7-D3: Preserve AND clusters when OR is mixed (e.g. ``A OR B AND C``).
|
||||
Collect each ``_parse_and_expr`` result as a separate cluster. When OR
|
||||
is found AND a cluster has >1 term (implicit AND), wrap it in a group
|
||||
so the engine produces ``A OR (B AND C)`` instead of ``A OR B OR C``.
|
||||
"""
|
||||
clusters = [self._parse_and_expr(result)]
|
||||
had_or = False
|
||||
while self.peek().type == TokenType.OR:
|
||||
had_or = True
|
||||
self.advance()
|
||||
if self.peek().type == TokenType.EOF:
|
||||
break # trailing OR, ignore silently
|
||||
right = self._parse_and_expr(result)
|
||||
left.extend(right)
|
||||
return left
|
||||
clusters.append(self._parse_and_expr(result))
|
||||
|
||||
if not had_or:
|
||||
return clusters[0] if clusters else []
|
||||
|
||||
# OR present: group any AND-cluster with >1 term
|
||||
all_terms: list[Term] = []
|
||||
for cluster in clusters:
|
||||
if len(cluster) > 1 and not any(t.group_id >= 0 for t in cluster):
|
||||
gid = len(result.groups)
|
||||
for t in cluster:
|
||||
t.group_id = gid
|
||||
result.groups.append(cluster)
|
||||
result.group_operators.append("and")
|
||||
all_terms.extend(cluster)
|
||||
return all_terms
|
||||
|
||||
def _is_primary_start(self, token: Token) -> bool:
|
||||
"""Check if token could start a primary expression."""
|
||||
|
||||
@@ -1195,6 +1195,12 @@ class AdvancedSearchEngine:
|
||||
cast(GlobalLiterature.pmid, String).ilike(like_val),
|
||||
GlobalLiterature.doi.ilike(like_val),
|
||||
)
|
||||
# P7-D2: Chinese → ILIKE fallback (tsvector is English-only)
|
||||
if re.search(r'[一-鿿㐀-䶿豈-]', term):
|
||||
return or_(
|
||||
GlobalLiterature.title.ilike(like_val),
|
||||
GlobalLiterature.abstract.ilike(like_val),
|
||||
)
|
||||
return GlobalLiterature.search_tsv.op("@@")(func.plainto_tsquery("english", term))
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user