fix(vector_stores/opensearch): translate the '*' wildcard to an exists query for every key (#6522)

This commit is contained in:
microbluey
2026-07-23 19:41:09 +05:30
committed by GitHub
parent ca2abca2b8
commit 56ec7d20f1
2 changed files with 48 additions and 4 deletions
+10 -2
View File
@@ -35,8 +35,16 @@ def _build_filter_clauses(filters):
for key, value in (filters or {}).items():
if value is None:
continue
if key not in _IDENTITY_FILTER_KEYS and (not isinstance(value, (str, int, float, bool)) or value == "*"):
logger.debug(f"Ignoring non-scalar or wildcard filter value for key {key!r}")
if value == "*":
# "Any value" wildcard (a documented Platform pattern): match
# documents where the field exists — as opensearch.ts already
# does for every key — instead of a literal, near-always-empty
# term match on the string "*".
_validate_filter(key, value)
filter_clauses.append({"exists": {"field": f"payload.{key}"}})
continue
if key not in _IDENTITY_FILTER_KEYS and not isinstance(value, (str, int, float, bool)):
logger.debug(f"Ignoring non-scalar filter value for key {key!r}")
continue
_validate_filter(key, value)
field = f"payload.{key}.keyword" if isinstance(value, str) else f"payload.{key}"
+38 -2
View File
@@ -643,13 +643,49 @@ class TestOpenSearchCustomFilters(TestOpenSearchFilterValidation):
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertEqual(clauses, [{"term": {"payload.user_id.keyword": "alice"}}])
def test_search_ignores_wildcard_filter_value(self):
def test_search_translates_wildcard_filter_value_to_exists(self):
self.os_db.search(query="", vectors=[[0.1] * 1536], filters={"user_id": "alice", "category": "*"})
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertEqual(clauses, [{"term": {"payload.user_id.keyword": "alice"}}])
self.assertEqual(
clauses,
[
{"term": {"payload.user_id.keyword": "alice"}},
{"exists": {"field": "payload.category"}},
],
)
def test_list_ignores_or_operator_filter(self):
self.os_db.list(filters={"user_id": "alice", "$or": [{"a": 1}]})
self.client_mock.search.assert_called_once()
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertEqual(clauses, [{"term": {"payload.user_id.keyword": "alice"}}])
class TestOpenSearchWildcardFilters(TestOpenSearchFilterValidation):
"""The "*" wildcard means "any value" (a documented Platform pattern) and
must build an exists query — as opensearch.ts does — for every key,
including the identity keys, instead of a literal term match on "*"."""
def setUp(self):
super().setUp()
self.client_mock.search.return_value = {"hits": {"hits": []}}
def _search_body(self):
return self.client_mock.search.call_args[1]["body"]
def test_identity_key_wildcard_builds_exists_query(self):
self.os_db.search(query="", vectors=[[0.1] * 1536], filters={"agent_id": "*"})
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertIn({"exists": {"field": "payload.agent_id"}}, clauses)
self.assertNotIn({"term": {"payload.agent_id.keyword": "*"}}, clauses)
def test_custom_key_wildcard_builds_exists_query(self):
self.os_db.list(filters={"category": "*"})
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertIn({"exists": {"field": "payload.category"}}, clauses)
def test_wildcard_combines_with_term_filters(self):
self.os_db.keyword_search(query="q", filters={"user_id": "u1", "topic": "*"})
clauses = self._search_body()["query"]["bool"]["filter"]
self.assertIn({"term": {"payload.user_id.keyword": "u1"}}, clauses)
self.assertIn({"exists": {"field": "payload.topic"}}, clauses)