Class: ParadeDB::Vector

Inherits:
ActiveModel::Type::Value
  • Object
show all
Defined in:
lib/parade_db/vector.rb

Defined Under Namespace

Modules: PostgreSQLAdapterPatch

Constant Summary collapse

METRICS =
%i[l2 cosine ip].freeze
METRIC_ALIASES =
{ inner_product: :ip }.freeze
OPCLASSES =
{ l2: "vector_l2_ops", cosine: "vector_cosine_ops", ip: "vector_ip_ops" }.freeze
METRICS_BY_OPCLASS =
OPCLASSES.invert.freeze
DISTANCE_OPERATORS =
{ l2: "<->", cosine: "<=>", ip: "<#>" }.freeze
DEFAULT_METRIC =
:l2

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(limit: nil) ⇒ Vector

Returns a new instance of Vector.



29
30
31
32
# File 'lib/parade_db/vector.rb', line 29

def initialize(limit: nil)
  super()
  @limit = limit
end

Instance Attribute Details

#limitObject (readonly)

Returns the value of attribute limit.



27
28
29
# File 'lib/parade_db/vector.rb', line 27

def limit
  @limit
end

Class Method Details

.install_postgresql_adapter!(adapter_class) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/parade_db/vector.rb', line 79

def self.install_postgresql_adapter!(adapter_class)
  adapter_class::NATIVE_DATABASE_TYPES[:vector] = { name: "vector" }

  unless adapter_class.singleton_class.ancestors.include?(PostgreSQLAdapterPatch)
    adapter_class.singleton_class.prepend(PostgreSQLAdapterPatch)
  end

  register_with_type_map(adapter_class::TYPE_MAP) if adapter_class.const_defined?(:TYPE_MAP)

  table_definition = ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition
  unless table_definition.method_defined?(:vector)
    table_definition.send(:define_column_methods, :vector)
  end
end

.literal(value) ⇒ Object



23
24
25
# File 'lib/parade_db/vector.rb', line 23

def self.literal(value)
  "[#{Array(value).map { |v| Float(v) }.join(',')}]"
end

.normalize_metric(metric) ⇒ Object

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
# File 'lib/parade_db/vector.rb', line 14

def self.normalize_metric(metric)
  normalized = metric.to_sym
  normalized = METRIC_ALIASES.fetch(normalized, normalized)
  return normalized if METRICS.include?(normalized)

  raise ArgumentError,
        "unknown vector metric #{metric.inspect}. Valid metrics: #{(METRICS + METRIC_ALIASES.keys).map(&:inspect).join(', ')}"
end

.register_with_type_map(m) ⇒ Object



65
66
67
68
69
70
# File 'lib/parade_db/vector.rb', line 65

def self.register_with_type_map(m)
  m.register_type "vector" do |_, _, sql_type|
    limit = sql_type.to_s[/\((\d+)\)/, 1]
    ParadeDB::Vector.new(limit: limit&.to_i)
  end
end

Instance Method Details

#cast(value) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/parade_db/vector.rb', line 38

def cast(value)
  case value
  when nil
    nil
  when Array
    validate_dimensions!(value.map { |v| Float(v) })
  when String
    cast_string(value)
  else
    raise ArgumentError, "cannot cast #{value.class} to vector"
  end
end

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/parade_db/vector.rb', line 61

def changed_in_place?(raw_old_value, new_value)
  deserialize(raw_old_value) != new_value
end

#deserialize(value) ⇒ Object



57
58
59
# File 'lib/parade_db/vector.rb', line 57

def deserialize(value)
  cast(value)
end

#serialize(value) ⇒ Object



51
52
53
54
55
# File 'lib/parade_db/vector.rb', line 51

def serialize(value)
  return nil if value.nil?

  self.class.literal(cast(value))
end

#typeObject



34
35
36
# File 'lib/parade_db/vector.rb', line 34

def type
  :vector
end