Context
PR #80's Where.eq(String key, Object value) accepts any Object — no compile-time type safety. The Go client has typed variants (EqString, EqInt, GtFloat). We need to bring that type safety to Java while keeping the API ergonomic.
Requirements
Where (metadata filtering)
public abstract class Where {
// Type-safe equality
static Where eq(String key, String value);
static Where eq(String key, int value);
static Where eq(String key, float value);
static Where eq(String key, boolean value);
// Type-safe comparison (numeric + string)
static Where ne(String key, String value);
static Where ne(String key, int value);
static Where ne(String key, float value);
static Where gt(String key, int value);
static Where gt(String key, float value);
static Where gte(String key, int value);
static Where gte(String key, float value);
static Where lt(String key, int value);
static Where lt(String key, float value);
static Where lte(String key, int value);
static Where lte(String key, float value);
// Set operations (type-safe)
static Where in(String key, List<String> values);
static Where in(String key, int... values);
static Where in(String key, float... values);
static Where nin(String key, List<String> values);
static Where nin(String key, int... values);
static Where nin(String key, float... values);
// Logical combinators
static Where and(Where... conditions);
static Where or(Where... conditions);
// Instance chaining (convenience)
Where and(Where other);
Where or(Where other);
// Serialization
abstract Map<String, Object> toMap();
}
WhereDocument (document content filtering)
public abstract class WhereDocument {
static WhereDocument contains(String text);
static WhereDocument notContains(String text);
static WhereDocument and(WhereDocument... conditions);
static WhereDocument or(WhereDocument... conditions);
abstract Map<String, Object> toMap();
}
Usage Examples
// Simple
Where.eq("type", "article")
// Compound
Where.and(
Where.eq("type", "article"),
Where.gt("views", 1000),
Where.in("status", List.of("published", "featured"))
)
// Chaining
Where.eq("type", "article").and(Where.gt("views", 1000))
// Document
WhereDocument.contains("machine learning")
Design Decisions
- Overloaded static methods per type —
eq(String, String), eq(String, int), eq(String, float) — instead of a single eq(String, Object). This gives compile-time safety.
- Abstract class, not interface — allows static factory methods (Java 8 compat) and internal subclasses
- Sealed hierarchy (or package-private subclasses) —
ComparisonWhere, LogicalWhere, etc. Users only interact via static factories.
toMap() for serialization — the HTTP layer calls toMap() to build the JSON request body
- No
Where.empty() — just use null or omit the parameter entirely
Acceptance Criteria
Supersedes
Context
PR #80's
Where.eq(String key, Object value)accepts any Object — no compile-time type safety. The Go client has typed variants (EqString,EqInt,GtFloat). We need to bring that type safety to Java while keeping the API ergonomic.Requirements
Where (metadata filtering)
WhereDocument (document content filtering)
Usage Examples
Design Decisions
eq(String, String),eq(String, int),eq(String, float)— instead of a singleeq(String, Object). This gives compile-time safety.ComparisonWhere,LogicalWhere, etc. Users only interact via static factories.toMap()for serialization — the HTTP layer callstoMap()to build the JSON request bodyWhere.empty()— just usenullor omit the parameter entirelyAcceptance Criteria
Whereclass with all typed static factory methodsWhereDocumentclass with contains/notContains and logical combinatorsWhere.gt("key", "not-a-number")for numeric-only opstoMap()produces correct Chroma filter JSON structureSupersedes