mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-02 10:17:10 +01:00
s3vectors: match a filter value against the elements of an array (#12321)
* vector: compare json_array_contains elements as typed JSON values Lance's json_array_contains compares each element's text with the value, or with the value wrapped in quotes, so 1 matches "1", true matches "true", and 1.0 misses a stored 1. The filter swap now replaces it like json_extract and json_exists: the value is parsed as JSON once per batch and compared with jsonb's typed equality, and only literal arguments are swapped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * s3vectors: match a filter value against the elements of an array A filter never looked inside an array: {"tags": "space"} and {"tags": {"$in": ["space"]}} both missed "tags": ["space", "classic"]. AWS documents that $eq, and so a bare value, matches an array metadata value when any element equals the input. $eq, a bare value and each $in member now also match through json_array_contains; $ne and $nin remain their negations. Range operators, $exists and nested objects are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
533f5060b9
commit
06b9d01423
4 files changed
+190
-39
No files matched your search
@@ -204,6 +204,25 @@ def test_filter_types(vectors, index):
|
||||
assert sorted(hit["key"] for hit in hits) == ["0", "3"]
|
||||
|
||||
|
||||
def test_filter_arrays(vectors, index):
|
||||
rows = {"space": ["space", "classic"], "nums": [1, 2.5], "strs": ["1", "2.5"], "flag": [True], "scalar": "space"}
|
||||
vectors.put_vectors(**index, vectors=[{"key": key, "data": {"float32": [1, 0, 0, 0]}, "metadata": {"tags": tags}}
|
||||
for key, tags in rows.items()])
|
||||
|
||||
def matches(condition):
|
||||
hits = vectors.query_vectors(**index, queryVector={"float32": [1, 0, 0, 0]}, topK=10,
|
||||
filter={"tags": condition})["vectors"]
|
||||
return sorted(hit["key"] for hit in hits)
|
||||
|
||||
assert matches("space") == ["scalar", "space"]
|
||||
assert matches({"$eq": 1}) == ["nums"]
|
||||
assert matches({"$eq": "1"}) == ["strs"]
|
||||
assert matches({"$eq": True}) == ["flag"]
|
||||
assert matches({"$in": ["classic", 2.5]}) == ["nums", "space"]
|
||||
assert matches({"$ne": "space"}) == ["flag", "nums", "strs"]
|
||||
assert matches({"$nin": [1, "2.5"]}) == ["flag", "scalar", "space"]
|
||||
|
||||
|
||||
def test_cosine_metric(vectors):
|
||||
bucket = "cosine-" + uuid.uuid4().hex[:16]
|
||||
vectors.create_vector_bucket(vectorBucketName=bucket)
|
||||
|
||||
Reference in new issue
Block a user