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.



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

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.



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

def schema
  @schema
end

Instance Method Details

#adapterObject



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

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

#allowed_attributesObject



188
189
190
# File 'lib/litestack/litesearch/schema.rb', line 188

def allowed_attributes
  [:weight, :col, :target, :source, :conditions, :reference]
end

#auto_create(boolean) ⇒ Object



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

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

#auto_modify(boolean) ⇒ Object



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

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

#cleanObject



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

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?



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
177
178
179
180
181
# File 'lib/litestack/litesearch/schema.rb', line 123

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



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

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



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

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

#filter_column(filter_column) ⇒ Object



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

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

#get(key) ⇒ Object

schema data structure API



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

def get(key)
  @schema[key]
end

#get_field(name) ⇒ Object



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

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

#merge(other_schema) ⇒ Object



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

def merge(other_schema)
  @schema.merge!(other_schema.schema)
end

#name(new_name) ⇒ Object

schema definition API



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

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

#order_fields(old_schema) ⇒ Object



118
119
120
# File 'lib/litestack/litesearch/schema.rb', line 118

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

#post_initObject



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

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

#rebuild_on_create(boolean) ⇒ Object



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

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

#rebuild_on_modify(boolean) ⇒ Object



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

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

#reset_sqlObject



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

def reset_sql
  adapter.generate_sql
end

#sql_for(method, *args) ⇒ Object

schema sql generation API



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

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

#table(table_name) ⇒ Object



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

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

#tokenizer(new_tokenizer) ⇒ Object



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

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

#type(new_type) ⇒ Object



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

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