fix: replace exact-phrase wrap with AND-required-terms in /search

Wrapping every multi-word phrase in exact-phrase quotes (added for the
"uyuşturucu madde ticareti" false-positive problem) was too strict for
independent keyword queries like "bıçak yaralaması beraat" or the AI
query-optimizer's extracted keywords — those words rarely appear
verbatim adjacent to each other, so exact-phrase returned 0 results.

Now each word is prefixed with + instead (AND semantics: all words
must appear somewhere in the decision, not necessarily adjacent).
This still fixes the original "madde" noise problem while no longer
breaking loose multi-keyword searches.
This commit is contained in:
mstfyldz
2026-08-09 10:55:34 +03:00
parent 2131e3c71d
commit 47ca4cc962
+23 -12
View File
@@ -52,10 +52,12 @@ class SearchRequest(BaseModel):
exact_phrase: bool = Field(
default=True,
description=(
"True ise coklu kelimeli phrase otomatik tam ifade (\"...\") aramasina cevrilir. "
"Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri eslestirir "
"(orn. 'madde' gibi her kararda gecen ortak kelimeler alakasiz sonuclari one cikarir); "
"tam ifade araması bu gurultuyu onler. Kullanici zaten tirnak/AND/OR/NOT/+/- kullaniyorsa dokunulmaz."
"True ise coklu kelimeli phrase'deki her kelime otomatik olarak '+' ile zorunlu "
"kilinir (orn. 'a b' -> '+a +b') — tum kelimeler karar icinde gecmeli ama yan yana "
"olmalari gerekmez. Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri gevsek "
"eslestirir (orn. 'madde' gibi her kararda gecen ortak kelimeler alakasiz sonuclari "
"one cikarir); bu ayar bu gurultuyu onler. Kullanici zaten tirnak/AND/OR/NOT/+/- "
"kullaniyorsa dokunulmaz."
),
)
@@ -95,25 +97,34 @@ def _format_date(value: Optional[str], end_of_day: bool = False) -> str:
return value
# --- Yardimci fonksiyon: coklu kelimeli aramalari tam ifadeye cevirme ---
# --- Yardimci fonksiyon: coklu kelimeli aramalari daha isabetli hale getirme ---
#
# Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri eslestiriyor.
# Bedesten API'de tirnaksiz coklu kelime aramasi kelimeleri ayri ayri (gevsek) eslestiriyor.
# Ornek: "uyusturucu madde ticareti" -> "madde" gibi her kararda gecen (kanun maddesi
# anlaminda) ortak bir kelime yuzunden alakasiz sonuclar (ic icra/iflas kararlari) one
# cikabiliyor. Kullanici zaten ozel operator/tirnak kullanmiyorsa, coklu kelimeli
# aramayi otomatik tam ifadeye ("...") ceviriyoruz.
# cikabiliyor.
#
# Once tum ifadeyi tirnaklayip "tam bitisik ifade" aramasi denendi, ama bu cok kati
# cikti: "bicak yaralamasi beraat" gibi bagimsiz anahtar kelimelerden olusan (AI'nin
# uzun sorulardan cikardigi turden) aramalar, bu 3 kelime kararlarda hic yan yana/aynen
# gecmedigi icin 0 sonuc donduruyordu. Bunun yerine her kelimeyi "+" ile ayri ayri
# zorunlu kiliyoruz (AND semantigi): tum kelimeler karar icinde herhangi bir yerde
# gecmeli ama bitisik/ayni sirada olmalari gerekmiyor. Bu hem orijinal "madde" sorununu
# cozuyor (uyusturucu VE madde VE ticaret hepsi gecmeli) hem de bagimsiz anahtar kelime
# aramalarini kirmiyor.
_OPERATOR_PATTERN = re.compile(r'"|\bAND\b|\bOR\b|\bNOT\b|(?:^|\s)[+-]\S', re.IGNORECASE)
def _apply_exact_phrase(phrase: str, exact_phrase: bool) -> str:
def _apply_required_terms(phrase: str, exact_phrase: bool) -> str:
stripped = phrase.strip()
if not exact_phrase or not stripped:
return phrase
if len(stripped.split()) < 2:
words = stripped.split()
if len(words) < 2:
return phrase
if _OPERATOR_PATTERN.search(stripped):
return phrase
return f'"{stripped}"'
return " ".join(f"+{w}" for w in words)
# --- Endpoint 1: Arama ---
@@ -126,7 +137,7 @@ async def search(req: SearchRequest):
"""
karar_tarihi_start = _format_date(req.karar_tarihi_start)
karar_tarihi_end = _format_date(req.karar_tarihi_end, end_of_day=True)
phrase = _apply_exact_phrase(req.phrase, req.exact_phrase)
phrase = _apply_required_terms(req.phrase, req.exact_phrase)
search_data = BedestenSearchData(
pageSize=10,