Skip to content

Commit b660dc9

Browse files
Merge branch 'master' into feat/redis-vector-search
2 parents 62f9256 + 3b98c22 commit b660dc9

2 files changed

Lines changed: 93 additions & 5 deletions

File tree

sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pathlib import Path
55
from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple, Union
66

7-
from pydantic import StrictStr
7+
from pydantic import StrictStr, field_validator
88
from pymilvus import (
99
CollectionSchema,
1010
DataType,
@@ -115,6 +115,14 @@ class MilvusOnlineStoreConfig(FeastConfigBaseModel, VectorStoreConfig):
115115
nlist: Optional[int] = 128
116116
username: Optional[StrictStr] = ""
117117
password: Optional[StrictStr] = ""
118+
varchar_max_length: Optional[int] = 65535
119+
120+
@field_validator("varchar_max_length")
121+
@classmethod
122+
def validate_varchar_max_length(cls, v):
123+
if v is not None and not (1 <= v <= 65535):
124+
raise ValueError(f"varchar_max_length must be between 1 and 65535, got {v}")
125+
return v
118126

119127

120128
class MilvusOnlineStore(OnlineStore):
@@ -171,12 +179,12 @@ def _get_or_create_collection(
171179
if collection_name not in self._collections:
172180
# Create a composite key by combining entity fields
173181
composite_key_name = _get_composite_key_name(table)
174-
182+
varchar_max_length = int(config.online_store.varchar_max_length or 65535)
175183
fields = [
176184
FieldSchema(
177185
name=composite_key_name,
178186
dtype=DataType.VARCHAR,
179-
max_length=512,
187+
max_length=varchar_max_length,
180188
is_primary=True,
181189
),
182190
FieldSchema(name="event_ts", dtype=DataType.INT64),
@@ -203,14 +211,28 @@ def _get_or_create_collection(
203211
)
204212
)
205213
else:
214+
if "max_length" in field.tags:
215+
try:
216+
field_max_length = int(field.tags["max_length"])
217+
except (ValueError, TypeError):
218+
raise ValueError(
219+
f"Field '{field.name}' has invalid max_length tag"
220+
f" '{field.tags['max_length']}': must be an integer."
221+
)
222+
if not (1 <= field_max_length <= 65535):
223+
raise ValueError(
224+
f"Field '{field.name}' max_length tag must be"
225+
f" between 1 and 65535, got {field_max_length}"
226+
)
227+
else:
228+
field_max_length = varchar_max_length
206229
fields.append(
207230
FieldSchema(
208231
name=field.name,
209232
dtype=DataType.VARCHAR,
210-
max_length=512,
233+
max_length=field_max_length,
211234
)
212235
)
213-
214236
schema = CollectionSchema(
215237
fields=fields, description="Feast feature view data"
216238
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Unit test for Milvus varchar_max_length configuration."""
2+
3+
from datetime import timedelta
4+
from unittest.mock import MagicMock, patch
5+
6+
import pytest
7+
from pydantic import ValidationError
8+
9+
from feast import Entity, FeatureView
10+
from feast.field import Field
11+
from feast.infra.online_stores.milvus_online_store.milvus import (
12+
MilvusOnlineStore,
13+
MilvusOnlineStoreConfig,
14+
)
15+
from feast.types import Float32, String
16+
from feast.value_type import ValueType
17+
18+
19+
@patch("feast.infra.online_stores.milvus_online_store.milvus.MilvusClient")
20+
def test_varchar_max_length(mock_client_cls):
21+
# -- config: default and custom values ------------------------------------
22+
assert MilvusOnlineStoreConfig().varchar_max_length == 65535
23+
assert MilvusOnlineStoreConfig(varchar_max_length=1024).varchar_max_length == 1024
24+
25+
# -- config: out-of-bounds values raise ValidationError -------------------
26+
for bad in (0, -1, 65536):
27+
with pytest.raises(ValidationError):
28+
MilvusOnlineStoreConfig(varchar_max_length=bad)
29+
30+
# -- schema: configured value reaches every VARCHAR FieldSchema -----------
31+
mock_client = MagicMock()
32+
mock_client_cls.return_value = mock_client
33+
mock_client.has_collection.return_value = False
34+
35+
entity = Entity(
36+
name="driver_id", join_keys=["driver_id"], value_type=ValueType.INT64
37+
)
38+
fv = FeatureView(
39+
name="driver_stats",
40+
entities=[entity],
41+
ttl=timedelta(days=1),
42+
schema=[
43+
Field(name="trips_today", dtype=Float32),
44+
Field(name="wiki_summary", dtype=String),
45+
],
46+
)
47+
48+
config = MagicMock()
49+
config.project = "test_project"
50+
config.entity_key_serialization_version = 2
51+
config.registry.enable_online_feature_view_versioning = False
52+
config.provider = "local"
53+
config.repo_path = None
54+
config.online_store = MilvusOnlineStoreConfig(varchar_max_length=4096)
55+
56+
store = MilvusOnlineStore()
57+
store._collections = {}
58+
store.client = mock_client
59+
store._get_or_create_collection(config, fv)
60+
61+
schema = mock_client.create_collection.call_args.kwargs["schema"]
62+
for field in schema.fields:
63+
if hasattr(field, "max_length") and field.max_length is not None:
64+
assert field.max_length == 4096, (
65+
f"field '{field.name}': got {field.max_length}"
66+
)

0 commit comments

Comments
 (0)