full_search 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/full_search/bulk_import.rb +13 -0
- data/lib/full_search/errors.rb +1 -0
- data/lib/full_search/index.rb +24 -13
- data/lib/full_search/multi_search.rb +31 -29
- data/lib/full_search/search.rb +15 -0
- data/lib/full_search/version.rb +1 -1
- data/lib/tasks/full_search.rake +7 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ffdca4041a68a79686da2b8d636b3feadb88d39fd6ca2ff8f3c6ec955d52355c
|
|
4
|
+
data.tar.gz: 8438b904a538c0d8c8e0250bf751209b44f8a095aacfc1089cb180a5cbb21d8f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 447a5e7b51909e3098a38439935facf534ad7a97c84eb399af7fbd5e844c966787ac74651a58993000d12b0c18d3a6851fe3ea1e32b854629ff97b5c9e1906a0
|
|
7
|
+
data.tar.gz: d43d646f9e95ad6bc8d4425c8601b9c5f2695f106965cba1b53881cf8e155581a3421055f1b6babc0468aaf0a02c589e1e615f95dfecb42cd776adebae320bb5
|
|
@@ -19,6 +19,19 @@ module FullSearch
|
|
|
19
19
|
models_in_bulk_import.delete(model)
|
|
20
20
|
FullSearch::Index.create_triggers!(model)
|
|
21
21
|
FullSearch::BackfillJob.perform_later(model.name)
|
|
22
|
+
rescue => e
|
|
23
|
+
# Triggers are still dropped at this point; the FTS index will rot on
|
|
24
|
+
# every subsequent write. Retry once, then raise loudly so the caller
|
|
25
|
+
# knows the index is compromised instead of failing silent.
|
|
26
|
+
retry_count = (Thread.current[:_fs_bulk_import_retry] ||= 0)
|
|
27
|
+
if retry_count < 1
|
|
28
|
+
Thread.current[:_fs_bulk_import_retry] = retry_count + 1
|
|
29
|
+
retry
|
|
30
|
+
end
|
|
31
|
+
raise FullSearch::TriggerRestoreError,
|
|
32
|
+
"Failed to restore FTS triggers for #{model.table_name} after bulk import: #{e.message}"
|
|
33
|
+
ensure
|
|
34
|
+
Thread.current[:_fs_bulk_import_retry] = nil
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
def bulk_importing?(model)
|
data/lib/full_search/errors.rb
CHANGED
data/lib/full_search/index.rb
CHANGED
|
@@ -267,6 +267,22 @@ module FullSearch
|
|
|
267
267
|
).any?
|
|
268
268
|
end
|
|
269
269
|
|
|
270
|
+
def missing_triggers?(model)
|
|
271
|
+
return false if FullSearch.bulk_importing?(model)
|
|
272
|
+
return false unless model_table_exists?(model)
|
|
273
|
+
return false unless table_exists?(model)
|
|
274
|
+
|
|
275
|
+
IndexCache.fetch("missing_triggers:#{model.table_name}") do
|
|
276
|
+
existing = connection.execute(
|
|
277
|
+
"SELECT name FROM sqlite_master WHERE type='trigger' AND tbl_name=#{q(model.table_name)}"
|
|
278
|
+
).map { |r| r["name"] }
|
|
279
|
+
|
|
280
|
+
expected = trigger_names(model)
|
|
281
|
+
expected += trigram_trigger_names(model) if trigram_table_needed?(model)
|
|
282
|
+
(expected - existing).any?
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
270
286
|
private
|
|
271
287
|
|
|
272
288
|
def connection
|
|
@@ -290,9 +306,11 @@ module FullSearch
|
|
|
290
306
|
end
|
|
291
307
|
|
|
292
308
|
def model_table_exists?(model)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
309
|
+
IndexCache.fetch("model_table_exists:#{model.table_name}") do
|
|
310
|
+
connection.execute(
|
|
311
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name=#{q(model.table_name)} LIMIT 1"
|
|
312
|
+
).any?
|
|
313
|
+
end
|
|
296
314
|
end
|
|
297
315
|
|
|
298
316
|
def table_exists?(model)
|
|
@@ -354,16 +372,7 @@ module FullSearch
|
|
|
354
372
|
|
|
355
373
|
def ensure_triggers!(model)
|
|
356
374
|
return if FullSearch.bulk_importing?(model)
|
|
357
|
-
|
|
358
|
-
existing = connection.execute(
|
|
359
|
-
"SELECT name FROM sqlite_master WHERE type='trigger' AND tbl_name=#{q(model.table_name)}"
|
|
360
|
-
).map { |r| r["name"] }
|
|
361
|
-
|
|
362
|
-
expected = trigger_names(model)
|
|
363
|
-
expected += trigram_trigger_names(model) if trigram_table_needed?(model)
|
|
364
|
-
return if (expected - existing).empty? && (existing - expected).empty?
|
|
365
|
-
|
|
366
|
-
rebuild!(model)
|
|
375
|
+
rebuild!(model) if missing_triggers?(model)
|
|
367
376
|
end
|
|
368
377
|
|
|
369
378
|
def trigger_names(model)
|
|
@@ -378,6 +387,8 @@ module FullSearch
|
|
|
378
387
|
%W[#{base}_ai #{base}_ad #{base}_au]
|
|
379
388
|
end
|
|
380
389
|
|
|
390
|
+
private
|
|
391
|
+
|
|
381
392
|
def insert_trigger_sql(model)
|
|
382
393
|
dsl = model.full_search_dsl
|
|
383
394
|
cols = dsl.fields + dsl.filters + extra_columns(model)
|
|
@@ -12,40 +12,42 @@ module FullSearch
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def call
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
IndexCache.with_cache do
|
|
16
|
+
searched = groups.map do |group|
|
|
17
|
+
model = fetch(group, :model)
|
|
18
|
+
raise FullSearch::NotConfiguredError, "#{model} is not full_search configured" unless model.full_search_dsl
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
filters = group[:filters] || {}
|
|
21
|
+
limit = positive_integer(group[:limit], 8)
|
|
22
|
+
offset = positive_integer(group[:offset], 0)
|
|
23
|
+
raw_limit = limit + 1
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
relation = model.full_search(
|
|
26
|
+
query,
|
|
27
|
+
filters: filters,
|
|
28
|
+
limit: raw_limit,
|
|
29
|
+
offset: offset,
|
|
30
|
+
highlight: group[:highlight],
|
|
31
|
+
highlight_fields: group[:highlight_fields],
|
|
32
|
+
matching_strategy: group[:matching_strategy],
|
|
33
|
+
per_strategy_limit: group[:per_strategy_limit],
|
|
34
|
+
scope: group[:scope],
|
|
35
|
+
includes: group[:includes]
|
|
36
|
+
)
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
records = relation.to_a
|
|
39
|
+
has_more = records.size > limit
|
|
40
|
+
records = records.first(limit) if has_more
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
group.slice(:key, :label, :icon, :model).merge(
|
|
43
|
+
results: records,
|
|
44
|
+
has_more: has_more,
|
|
45
|
+
total_count: records.size
|
|
46
|
+
)
|
|
47
|
+
end
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
{groups: searched, total_count: searched.sum { |g| g[:total_count] }}
|
|
50
|
+
end
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
private
|
data/lib/full_search/search.rb
CHANGED
|
@@ -92,6 +92,21 @@ module FullSearch
|
|
|
92
92
|
raise MissingTableError, "FTS table `#{FullSearch::Index.fts_table_name(model)}` does not exist. Run `bin/rails full_search:prepare` to create it."
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
if FullSearch::Index.missing_triggers?(model)
|
|
96
|
+
if FullSearch.config.auto_rebuild_on_stale_query
|
|
97
|
+
FullSearch::Index.rebuild!(model)
|
|
98
|
+
return
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
case FullSearch.config.stale_query_behavior
|
|
102
|
+
when :raise
|
|
103
|
+
raise ConfigChangedError, "FTS triggers for #{model.table_name} are missing; run full_search:rebuild"
|
|
104
|
+
when :log_and_fallback
|
|
105
|
+
Rails.logger.warn("[full_search] FTS triggers for #{model.table_name} are missing; results may be incomplete")
|
|
106
|
+
end
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
|
|
95
110
|
stored = begin
|
|
96
111
|
FullSearch::Index.stored_config_hash(model)
|
|
97
112
|
rescue ActiveRecord::StatementInvalid
|
data/lib/full_search/version.rb
CHANGED
data/lib/tasks/full_search.rake
CHANGED
|
@@ -105,7 +105,9 @@ namespace :full_search do
|
|
|
105
105
|
""
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
trigger_info = FullSearch::Index.missing_triggers?(model) ? " | MISSING TRIGGERS" : ""
|
|
109
|
+
|
|
110
|
+
puts "#{model.table_name}: #{status}#{drift_info}#{trigger_info}"
|
|
109
111
|
end
|
|
110
112
|
end
|
|
111
113
|
|
|
@@ -120,6 +122,10 @@ namespace :full_search do
|
|
|
120
122
|
next
|
|
121
123
|
end
|
|
122
124
|
|
|
125
|
+
if FullSearch::Index.missing_triggers?(model)
|
|
126
|
+
unhealthy << "#{model.table_name}: missing FTS triggers"
|
|
127
|
+
end
|
|
128
|
+
|
|
123
129
|
stored = FullSearch::Index.stored_config_hash(model)
|
|
124
130
|
current = model.full_search_dsl.config_hash
|
|
125
131
|
if stored != current
|