Class: Litesearch::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/litestack/litesearch.rb,
lib/litestack/litesearch/schema.rb

Defined Under Namespace

Classes: BackedAdapter, BasicAdapter, ContentlessAdapter, StandaloneAdapter

Constant Summary collapse

TOKENIZERS =
{
  porter: "porter unicode61 remove_diacritics 2",
  unicode: "unicode61 remove_diacritics 2",
  ascii: "ascii",
  trigram: "trigram"
}
INDEX_TYPES =
{
  standalone: Litesearch::Schema::StandaloneAdapter,
  contentless: Litesearch::Schema::ContentlessAdapter,
  backed: Litesearch::Schema::BackedAdapter
}
DEFAULT_SCHEMA =
{
  name: nil,
  type: :standalone,
  fields: nil,
  table: nil,
  filter_column: nil,
  tokenizer: :porter,
  auto_create: true,
  auto_modify: true,
  rebuild_on_create: false,
  rebuild_on_modify: false
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema = {}) ⇒ Schema

Returns a new instance of Schema.



32
33
34
35
# File 'lib/litestack/litesearch/schema.rb', line 32

def initialize(schema = {})
  @schema = schema # DEFAULT_SCHEMA.merge(schema)
  @schema[:fields] = {} unless @schema[:fields]
end

Instance Attribute Details

#schemaObject

Returns the value of attribute schema.



30
31
32
# File 'lib/litestack/litesearch/schema.rb', line 30

def schema
  @schema
end

Instance Method Details

#adapterObject



105
106
107
# File 'lib/litestack/litesearch/schema.rb', line 105

def adapter
  @adapter ||= INDEX_TYPES[@schema[:type]].new(@schema)
end

#allowed_attributesObject



183
184
185
# File 'lib/litestack/litesearch/schema.rb', line 183

def allowed_attributes
  [:weight, :col, :target]
end

#auto_create(boolean) ⇒ Object



70
71
72
# File 'lib/litestack/litesearch/schema.rb', line 70

def auto_create(boolean)
  @schema[:auto_create] = boolean
end

#auto_modify(boolean) ⇒ Object



74
75
76
# File 'lib/litestack/litesearch/schema.rb', line 74

def auto_modify(boolean)
  @schema[:auto_modify] = boolean
end

#cleanObject



178
179
180
181
# File 'lib/litestack/litesearch/schema.rb', line 178

def clean
  removable = @schema[:fields].select { |name, f| f[:weight] == 0 }.collect { |name, f| name }
  removable.each { |name| @schema[:fields].delete(name) }
end

#compare(other_schema) ⇒ Object

should we do this at the schema objects level?



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/litestack/litesearch/schema.rb', line 118

def compare(other_schema)
  other_schema = other_schema.schema
  # are the schemas identical?
  # 1 - same fields?
  [:type, :tokenizer, :name, :table].each do |key|
    other_schema[key] = @schema[key] if other_schema[key].nil?
  end
  if @schema[:type] != other_schema[:type]
    raise Litesearch::SchemaChangeException.new "Cannot change the index type, please drop the index before creating it again with the new type"
  end
  changes = {tokenizer: @schema[:tokenizer] != other_schema[:tokenizer], table: @schema[:table] != other_schema[:table], removed_fields_count: 0, filter_column: @schema[:filter_column] != other_schema[:filter_column]}
  # check tokenizer changes
  if changes[:tokenizer] && !other_schema[:rebuild_on_modify]
    raise Litesearch::SchemaChangeException.new "Cannot change the tokenizer without an index rebuild!"
  end

  # check field changes
  keys = @schema[:fields].keys.sort
  other_keys = other_schema[:fields].keys.sort

  extra_keys = other_keys - keys
  extra_keys.each do |key|
    if other_schema[:fields][key][:weight] == 0
      other_schema[:fields].delete(key)
    end
  end

  other_keys = other_schema[:fields].keys.sort

  changes[:fields] = keys != other_keys # only acceptable change is adding extra fields
  changes[:extra_fields_count] = other_keys.count - keys.count
  # check for missing fields (please note that adding fields can work without a rebuild)
  if keys - other_keys != []
    raise Litesearch::SchemaChangeException.new "Missing fields from existing schema, they have to exist with weight zero until the next rebuild!"
  end

  # check field weights
  weights = keys.collect { |key| @schema[:fields][key][:weight] }
  other_weights = other_keys.collect { |key| other_schema[:fields][key][:weight] }
  changes[:weights] = weights != other_weights # will always be true if fields are added
  if (removed_count = other_weights.count { |w| w == 0 }) > 0
    changes[:removed_fields_count] = removed_count
  end
  # check field attributes, only backed tables have attributes
  attrs = keys.collect do |key|
    f = @schema[:fields][key].dup
    f.delete(:weight)
    f.select { |k, v| allowed_attributes.include? k }
  end
  other_attrs = other_keys.collect do |key|
    f = other_schema[:fields][key].dup
    f.delete(:weight)
    f.select { |k, v| allowed_attributes.include? k }
  end
  changes[:attributes] if other_attrs != attrs # this means that we will need to redefine the triggers if any are there and also the table definition if needed

  # return the changes
  changes
end

#field(name, attributes = {}) ⇒ Object



55
56
57
58
59
# File 'lib/litestack/litesearch/schema.rb', line 55

def field(name, attributes = {})
  name = name.to_s.downcase.to_sym
  attributes = {weight: 1}.merge(attributes).select { |k, v| allowed_attributes.include?(k) } # only allow attributes we know, to ease schema comparison later
  @schema[:fields][name] = attributes
end

#fields(field_names) ⇒ Object



51
52
53
# File 'lib/litestack/litesearch/schema.rb', line 51

def fields(field_names)
  field_names.each { |f| field f }
end

#filter_column(filter_column) ⇒ Object



66
67
68
# File 'lib/litestack/litesearch/schema.rb', line 66

def filter_column(filter_column)
  @schema[:filter_column] = filter_column
end

#get(key) ⇒ Object

schema data structure API



97
98
99
# File 'lib/litestack/litesearch/schema.rb', line 97

def get(key)
  @schema[key]
end

#get_field(name) ⇒ Object



101
102
103
# File 'lib/litestack/litesearch/schema.rb', line 101

def get_field(name)
  @schema[:fields][name]
end

#name(new_name) ⇒ Object

schema definition API



38
39
40
# File 'lib/litestack/litesearch/schema.rb', line 38

def name(new_name)
  @schema[:name] = new_name
end

#order_fields(old_schema) ⇒ Object



113
114
115
# File 'lib/litestack/litesearch/schema.rb', line 113

def order_fields(old_schema)
  adapter.order_fields(old_schema)
end

#post_initObject



86
87
88
# File 'lib/litestack/litesearch/schema.rb', line 86

def post_init
  @schema = DEFAULT_SCHEMA.merge(@schema)
end

#rebuild_on_create(boolean) ⇒ Object



78
79
80
# File 'lib/litestack/litesearch/schema.rb', line 78

def rebuild_on_create(boolean)
  @schema[:rebuild_on_create] = boolean
end

#rebuild_on_modify(boolean) ⇒ Object



82
83
84
# File 'lib/litestack/litesearch/schema.rb', line 82

def rebuild_on_modify(boolean)
  @schema[:rebuild_on_modify] = boolean
end

#reset_sqlObject



109
110
111
# File 'lib/litestack/litesearch/schema.rb', line 109

def reset_sql
  adapter.generate_sql
end

#sql_for(method, *args) ⇒ Object

schema sql generation API



92
93
94
# File 'lib/litestack/litesearch/schema.rb', line 92

def sql_for(method, *args)
  adapter.sql_for(method, *args)
end

#table(table_name) ⇒ Object



47
48
49
# File 'lib/litestack/litesearch/schema.rb', line 47

def table(table_name)
  @schema[:table] = table_name
end

#tokenizer(new_tokenizer) ⇒ Object



61
62
63
64
# File 'lib/litestack/litesearch/schema.rb', line 61

def tokenizer(new_tokenizer)
  raise "Unknown tokenizer" if TOKENIZERS[new_tokenizer].nil?
  @schema[:tokenizer] = new_tokenizer
end

#type(new_type) ⇒ Object



42
43
44
45
# File 'lib/litestack/litesearch/schema.rb', line 42

def type(new_type)
  raise "Unknown index type" if INDEX_TYPES[new_type].nil?
  @schema[:type] = new_type
end