Class: Zvec::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/zvec/schema.rb

Overview

Defines the structure of a collection: its name, fields, types, and vector dimensions.

Schemas are immutable once created -- fields can be added during initialization but not removed afterward.

Examples:

Creating a schema with a DSL block

schema = Zvec::Schema.new("articles") do
  string "title"
  string "body", nullable: true
  int32  "year"
  float  "rating"
  bool   "published"
  vector "embedding", dimension: 384,
         index: Zvec::Ext::HnswIndexParams.new(Zvec::COSINE)
end

Binary vector field

schema = Zvec::Schema.new("hashes") do
  field "hash_vec", DataTypes::BINARY, dimension: 128
end

Sparse vector field

schema = Zvec::Schema.new("sparse_docs") do
  field "tfidf", DataTypes::SPARSE_VECTOR_FP32, dimension: 30000
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) { ... } ⇒ Schema

Create a new schema.

Examples:

schema = Zvec::Schema.new("my_collection") do
  string "title"
  vector "embedding", dimension: 128
end

Parameters:

  • name (String, Symbol)

    the collection name (must be non-empty)

Yields:

  • optional DSL block evaluated in the schema's context

Raises:



44
45
46
47
48
49
50
51
52
53
# File 'lib/zvec/schema.rb', line 44

def initialize(name, &block)
  if name.nil? || name.to_s.strip.empty?
    raise SchemaError, "Schema name must be a non-empty string"
  end

  @ext_schema = Ext::CollectionSchema.new(name.to_s)
  @field_types = {}
  @field_dimensions = {}
  instance_eval(&block) if block
end

Instance Attribute Details

#ext_schemaExt::CollectionSchema (readonly)

Returns the underlying C++ schema object.

Returns:

  • (Ext::CollectionSchema)

    the underlying C++ schema object



31
32
33
# File 'lib/zvec/schema.rb', line 31

def ext_schema
  @ext_schema
end

Instance Method Details

#bool(name, **opts) ⇒ self

Add a boolean field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field

Returns:

  • (self)


164
165
166
# File 'lib/zvec/schema.rb', line 164

def bool(name, **opts)
  field(name, DataTypes::BOOL, **opts)
end

#double(name, **opts) ⇒ self

Add a 64-bit double field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field

Returns:

  • (self)


155
156
157
# File 'lib/zvec/schema.rb', line 155

def double(name, **opts)
  field(name, DataTypes::DOUBLE, **opts)
end

#field(name, type, dimension: nil, nullable: false, index: nil) ⇒ self

Add a field with an explicit data type.

Examples:

schema.field("tags", DataTypes::ARRAY_STRING)
schema.field("embedding", DataTypes::VECTOR_FP32, dimension: 128)

Parameters:

  • name (String, Symbol)

    the field name (must be non-empty)

  • type (Symbol)

    a DataTypes constant (e.g., DataTypes::STRING)

  • dimension (Integer, nil) (defaults to: nil)

    required for vector fields

  • nullable (Boolean) (defaults to: false)

    whether the field allows null values

  • index (Ext::HnswIndexParams, Ext::FlatIndexParams, Ext::IVFIndexParams, nil) (defaults to: nil)

    optional index parameters for this field

Returns:

  • (self)

    for method chaining

Raises:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/zvec/schema.rb', line 69

def field(name, type, dimension: nil, nullable: false, index: nil)
  name = name.to_s
  if name.strip.empty?
    raise SchemaError, "Field name must be a non-empty string"
  end

  fs = Ext::FieldSchema.new(name, type)
  fs.dimension = dimension if dimension
  fs.nullable = nullable
  fs.set_index_params(index) if index
  @ext_schema.add_field(fs)
  @field_types[name] = type
  @field_dimensions[name] = dimension if dimension
  self
end

#field_dimension(name) ⇒ Integer?

Look up the dimension of a vector field.

Parameters:

  • name (String, Symbol)

    the field name

Returns:

  • (Integer, nil)

    the dimension, or nil if the field is not a vector



190
191
192
# File 'lib/zvec/schema.rb', line 190

def field_dimension(name)
  @field_dimensions[name.to_s]
end

#field_namesArray<String>

Returns all field names in this schema.

Returns:

  • (Array<String>)

    all field names in this schema



174
175
176
# File 'lib/zvec/schema.rb', line 174

def field_names
  @ext_schema.field_names
end

#field_type(name) ⇒ Symbol?

Look up the data type of a field by name.

Parameters:

  • name (String, Symbol)

    the field name

Returns:

  • (Symbol, nil)

    the data type constant, or nil if not found



182
183
184
# File 'lib/zvec/schema.rb', line 182

def field_type(name)
  @field_types[name.to_s]
end

#float(name, **opts) ⇒ self

Add a 32-bit float field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field

Returns:

  • (self)


146
147
148
# File 'lib/zvec/schema.rb', line 146

def float(name, **opts)
  field(name, DataTypes::FLOAT, **opts)
end

#has_field?(name) ⇒ Boolean

Check whether a field exists in the schema.

Parameters:

  • name (String, Symbol)

    the field name

Returns:

  • (Boolean)


198
199
200
# File 'lib/zvec/schema.rb', line 198

def has_field?(name)
  @ext_schema.has_field?(name.to_s)
end

#int32(name, **opts) ⇒ self

Add a 32-bit integer field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field

Returns:

  • (self)


128
129
130
# File 'lib/zvec/schema.rb', line 128

def int32(name, **opts)
  field(name, DataTypes::INT32, **opts)
end

#int64(name, **opts) ⇒ self

Add a 64-bit integer field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field

Returns:

  • (self)


137
138
139
# File 'lib/zvec/schema.rb', line 137

def int64(name, **opts)
  field(name, DataTypes::INT64, **opts)
end

#nameString

Returns the collection name.

Returns:

  • (String)

    the collection name



169
170
171
# File 'lib/zvec/schema.rb', line 169

def name
  @ext_schema.name
end

#string(name, **opts) ⇒ self

Add a string field.

Parameters:

  • name (String, Symbol)

    the field name

  • opts (Hash)

    options passed to #field (+nullable:+, index:)

Returns:

  • (self)


119
120
121
# File 'lib/zvec/schema.rb', line 119

def string(name, **opts)
  field(name, DataTypes::STRING, **opts)
end

#to_sString

Returns human-readable representation of the schema.

Returns:

  • (String)

    human-readable representation of the schema



210
211
212
# File 'lib/zvec/schema.rb', line 210

def to_s
  @ext_schema.to_s
end

#vector(name, dimension:, type: DataTypes::VECTOR_FP32, index: nil) ⇒ self

Add a dense vector field. Defaults to FP32 precision.

Examples:

Standard FP32 vector with HNSW index

schema.vector "embedding", dimension: 384,
              index: Ext::HnswIndexParams.new(Zvec::COSINE)

FP16 vector (half memory)

schema.vector "embedding", dimension: 384,
              type: DataTypes::VECTOR_FP16

INT8 quantized vector (minimal memory)

schema.vector "embedding", dimension: 384,
              type: DataTypes::VECTOR_INT8

Parameters:

Returns:

  • (self)

Raises:

  • (ArgumentError)

    if dimension is not a positive integer



108
109
110
111
112
# File 'lib/zvec/schema.rb', line 108

def vector(name, dimension:, type: DataTypes::VECTOR_FP32, index: nil)
  raise ArgumentError, "Vector dimension must be a positive integer, got #{dimension.inspect}" unless dimension.is_a?(Integer) && dimension > 0

  field(name, type, dimension: dimension, index: index)
end

#vector_fields_with_dimensionsHash{String => Integer}

Returns a hash of vector field names to their dimensions.

Returns:

  • (Hash{String => Integer})

    e.g. {"embedding" => 384}



205
206
207
# File 'lib/zvec/schema.rb', line 205

def vector_fields_with_dimensions
  @field_dimensions.select { |name, _| DataTypes::VECTOR_TYPES.include?(@field_types[name]) }
end