searchkick.rb
4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
require "searchkick/version"
require "searchkick/tasks"
require "tire"
module Searchkick
module ClassMethods
# https://gist.github.com/jarosan/3124884
def reindex
alias_name = klass.tire.index.name
new_index = alias_name + "_" + Time.now.strftime("%Y%m%d%H%M%S")
# Rake::Task["tire:import"].invoke
index = Tire::Index.new(new_index)
Tire::Tasks::Import.create_index(index, klass)
scope = klass.respond_to?(:tire_import) ? klass.tire_import : klass
scope.find_in_batches do |batch|
index.import batch
end
if a = Tire::Alias.find(alias_name)
puts "[IMPORT] Alias found: #{Tire::Alias.find(alias_name).indices.to_ary.join(",")}"
old_indices = Tire::Alias.find(alias_name).indices
old_indices.each do |index|
a.indices.delete index
end
a.indices.add new_index
a.save
old_indices.each do |index|
puts "[IMPORT] Deleting index: #{index}"
i = Tire::Index.new(index)
i.delete if i.exists?
end
else
puts "[IMPORT] No alias found. Deleting index, creating new one, and setting up alias"
i = Tire::Index.new(alias_name)
i.delete if i.exists?
Tire::Alias.create(name: alias_name, indices: [new_index])
end
puts "[IMPORT] Saved alias #{alias_name} pointing to #{new_index}"
end
end
# can't check mapping for conversions since the new index may not be built
module SearchMethods
def searchkick_query(fields, term, conversions = false)
query do
boolean do
should do
match fields, term, boost: 10, operator: "and", analyzer: "searchkick_search"
end
should do
match fields, term, use_dis_max: false, fuzziness: 0.7, max_expansions: 1, prefix_length: 1, operator: "and", analyzer: "searchkick_search"
end
if conversions
should do
nested path: "conversions", score_mode: "total" do
query do
custom_score script: "log(doc['count'].value)" do
match "query", term
end
end
end
end
end
end
end
end
end
# TODO fix this monstrosity
# TODO add custom synonyms
def self.settings(options = {})
synonyms = options[:synonyms] || []
settings = {
analysis: {
analyzer: {
searchkick_keyword: {
type: "custom",
tokenizer: "keyword",
filter: ["lowercase", "snowball"]
},
searchkick: {
type: "custom",
tokenizer: "standard",
# synonym should come last, after stemming and shingle
# shingle must come before snowball
filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_index_shingle", "snowball"]
},
searchkick_search: {
type: "custom",
tokenizer: "standard",
filter: ["standard", "lowercase", "asciifolding", "stop", "searchkick_search_shingle", "snowball"]
}
},
filter: {
searchkick_index_shingle: {
type: "shingle",
token_separator: ""
},
# lucky find http://web.archiveorange.com/archive/v/AAfXfQ17f57FcRINsof7
searchkick_search_shingle: {
type: "shingle",
token_separator: "",
output_unigrams: false,
output_unigrams_if_no_shingles: true
}
}
}
}
if synonyms.any?
settings[:analysis][:filter][:searchkick_synonym] = {
type: "synonym",
ignore_case: true,
synonyms: synonyms
}
settings[:analysis][:analyzer][:searchkick][:filter] << "searchkick_synonym"
settings[:analysis][:analyzer][:searchkick_search][:filter] << "searchkick_synonym"
end
settings
end
end
Tire::Model::Search::ClassMethodsProxy.send :include, Searchkick::ClassMethods
Tire::Search::Search.send :include, Searchkick::SearchMethods