thinking-sphinx 3.0.6 → 3.1.0
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/.travis.yml +11 -6
- data/Appraisals +5 -5
- data/Gemfile +3 -3
- data/HISTORY +32 -0
- data/README.textile +16 -5
- data/gemfiles/rails_3_2.gemfile +2 -1
- data/gemfiles/rails_4_0.gemfile +3 -2
- data/gemfiles/{rails_3_1.gemfile → rails_4_1.gemfile} +3 -2
- data/lib/thinking_sphinx.rb +5 -0
- data/lib/thinking_sphinx/active_record.rb +2 -1
- data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +1 -1
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +6 -7
- data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +2 -2
- data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +1 -1
- data/lib/thinking_sphinx/active_record/column_sql_presenter.rb +34 -0
- data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +4 -0
- data/lib/thinking_sphinx/active_record/database_adapters/postgresql_adapter.rb +4 -0
- data/lib/thinking_sphinx/active_record/index.rb +2 -1
- data/lib/thinking_sphinx/active_record/interpreter.rb +7 -0
- data/lib/thinking_sphinx/active_record/property.rb +1 -1
- data/lib/thinking_sphinx/active_record/property_sql_presenter.rb +10 -16
- data/lib/thinking_sphinx/active_record/sql_builder.rb +7 -1
- data/lib/thinking_sphinx/active_record/sql_builder/query.rb +0 -7
- data/lib/thinking_sphinx/active_record/sql_source.rb +20 -20
- data/lib/thinking_sphinx/active_record/sql_source/template.rb +1 -1
- data/lib/thinking_sphinx/capistrano.rb +6 -65
- data/lib/thinking_sphinx/capistrano/v2.rb +58 -0
- data/lib/thinking_sphinx/capistrano/v3.rb +101 -0
- data/lib/thinking_sphinx/configuration.rb +8 -3
- data/lib/thinking_sphinx/configuration/distributed_indices.rb +29 -0
- data/lib/thinking_sphinx/connection.rb +90 -34
- data/lib/thinking_sphinx/controller.rb +20 -0
- data/lib/thinking_sphinx/core/index.rb +4 -0
- data/lib/thinking_sphinx/deletion.rb +15 -11
- data/lib/thinking_sphinx/deltas.rb +9 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +2 -0
- data/lib/thinking_sphinx/distributed.rb +5 -0
- data/lib/thinking_sphinx/distributed/index.rb +24 -0
- data/lib/thinking_sphinx/excerpter.rb +7 -3
- data/lib/thinking_sphinx/facet_search.rb +1 -1
- data/lib/thinking_sphinx/index.rb +2 -6
- data/lib/thinking_sphinx/index_set.rb +10 -8
- data/lib/thinking_sphinx/middlewares.rb +0 -2
- data/lib/thinking_sphinx/middlewares/active_record_translator.rb +1 -0
- data/lib/thinking_sphinx/middlewares/geographer.rb +1 -1
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +8 -6
- data/lib/thinking_sphinx/middlewares/utf8.rb +6 -1
- data/lib/thinking_sphinx/query.rb +9 -0
- data/lib/thinking_sphinx/railtie.rb +0 -13
- data/lib/thinking_sphinx/search/query.rb +3 -21
- data/lib/thinking_sphinx/sphinxql.rb +1 -1
- data/lib/thinking_sphinx/wildcard.rb +34 -0
- data/spec/acceptance/geosearching_spec.rb +13 -0
- data/spec/acceptance/indexing_spec.rb +27 -0
- data/spec/acceptance/remove_deleted_records_spec.rb +8 -0
- data/spec/acceptance/searching_with_sti_spec.rb +7 -0
- data/spec/acceptance/searching_within_a_model_spec.rb +8 -0
- data/spec/acceptance/sorting_search_results_spec.rb +1 -1
- data/spec/acceptance/spec_helper.rb +13 -0
- data/spec/acceptance/specifying_sql_spec.rb +2 -2
- data/spec/acceptance/support/sphinx_controller.rb +5 -5
- data/spec/acceptance/support/sphinx_helpers.rb +3 -0
- data/spec/acceptance/suspended_deltas_spec.rb +34 -0
- data/spec/internal/config/database.yml +1 -0
- data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +13 -6
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +2 -2
- data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +7 -0
- data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +6 -0
- data/spec/thinking_sphinx/active_record/interpreter_spec.rb +27 -0
- data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +18 -7
- data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +17 -7
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +84 -82
- data/spec/thinking_sphinx/configuration_spec.rb +5 -4
- data/spec/thinking_sphinx/connection_spec.rb +1 -1
- data/spec/thinking_sphinx/deletion_spec.rb +10 -28
- data/spec/thinking_sphinx/excerpter_spec.rb +3 -3
- data/spec/thinking_sphinx/facet_search_spec.rb +13 -4
- data/spec/thinking_sphinx/index_set_spec.rb +9 -4
- data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +8 -0
- data/spec/thinking_sphinx/middlewares/geographer_spec.rb +7 -7
- data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +17 -1
- data/spec/thinking_sphinx/search/query_spec.rb +10 -53
- data/spec/thinking_sphinx/wildcard_spec.rb +41 -0
- data/thinking-sphinx.gemspec +6 -5
- metadata +38 -14
- data/lib/thinking_sphinx/active_record/associations.rb +0 -98
- data/spec/thinking_sphinx/active_record/associations_spec.rb +0 -230
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class ThinkingSphinx::Controller < Riddle::Controller
|
|
2
|
+
def index(*indices)
|
|
3
|
+
options = indices.extract_options!
|
|
4
|
+
indices << '--all' if indices.empty?
|
|
5
|
+
|
|
6
|
+
indices = indices.reject { |index| File.exists? guard_file(index) }
|
|
7
|
+
return if indices.empty?
|
|
8
|
+
|
|
9
|
+
indices.each { |index| FileUtils.touch guard_file(index) }
|
|
10
|
+
super(*(indices + [options]))
|
|
11
|
+
indices.each { |index| FileUtils.rm guard_file(index) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def guard_file(index)
|
|
15
|
+
File.join(
|
|
16
|
+
ThinkingSphinx::Configuration.instance.indices_location,
|
|
17
|
+
"ts-#{index}.tmp"
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
class ThinkingSphinx::Deletion
|
|
2
2
|
delegate :name, :to => :index
|
|
3
3
|
|
|
4
|
-
def self.perform(index,
|
|
4
|
+
def self.perform(index, ids)
|
|
5
|
+
return if index.distributed?
|
|
6
|
+
|
|
5
7
|
{
|
|
6
8
|
'plain' => PlainDeletion,
|
|
7
9
|
'rt' => RealtimeDeletion
|
|
8
|
-
}[index.type].new(index,
|
|
10
|
+
}[index.type].new(index, ids).perform
|
|
9
11
|
rescue ThinkingSphinx::ConnectionError => error
|
|
10
12
|
# This isn't vital, so don't raise the error.
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def initialize(index,
|
|
14
|
-
@index, @
|
|
15
|
+
def initialize(index, ids)
|
|
16
|
+
@index, @ids = index, Array(ids)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
private
|
|
18
20
|
|
|
19
|
-
attr_reader :index, :
|
|
21
|
+
attr_reader :index, :ids
|
|
20
22
|
|
|
21
|
-
def
|
|
22
|
-
index.document_id_for_key
|
|
23
|
+
def document_ids_for_keys
|
|
24
|
+
ids.collect { |id| index.document_id_for_key id }
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def execute(statement)
|
|
@@ -30,15 +32,17 @@ class ThinkingSphinx::Deletion
|
|
|
30
32
|
|
|
31
33
|
class RealtimeDeletion < ThinkingSphinx::Deletion
|
|
32
34
|
def perform
|
|
33
|
-
execute Riddle::Query::Delete.new(name,
|
|
35
|
+
execute Riddle::Query::Delete.new(name, document_ids_for_keys).to_sql
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
class PlainDeletion < ThinkingSphinx::Deletion
|
|
38
40
|
def perform
|
|
39
|
-
execute
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
execute <<-SQL
|
|
42
|
+
UPDATE #{name}
|
|
43
|
+
SET sphinx_deleted = 1
|
|
44
|
+
WHERE id IN (#{document_ids_for_keys.join(', ')})
|
|
45
|
+
SQL
|
|
42
46
|
end
|
|
43
47
|
end
|
|
44
48
|
end
|
|
@@ -30,6 +30,15 @@ module ThinkingSphinx::Deltas
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def self.suspend_and_update(reference, &block)
|
|
34
|
+
suspend reference, &block
|
|
35
|
+
|
|
36
|
+
ids = reference.to_s.camelize.constantize.where(delta: true).pluck(:id)
|
|
37
|
+
config.indices_for_references(reference).each do |index|
|
|
38
|
+
ThinkingSphinx::Deletion.perform index, ids unless index.delta?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
33
42
|
def self.suspend!
|
|
34
43
|
@suspended = true
|
|
35
44
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class ThinkingSphinx::Distributed::Index <
|
|
2
|
+
Riddle::Configuration::DistributedIndex
|
|
3
|
+
|
|
4
|
+
attr_reader :reference, :options
|
|
5
|
+
|
|
6
|
+
def initialize(reference)
|
|
7
|
+
@reference = reference
|
|
8
|
+
@options = {}
|
|
9
|
+
|
|
10
|
+
super reference.to_s.gsub('/', '_')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def delta?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def distributed?
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def model
|
|
22
|
+
@model ||= reference.to_s.camelize.constantize
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -15,11 +15,10 @@ class ThinkingSphinx::Excerpter
|
|
|
15
15
|
|
|
16
16
|
def excerpt!(text)
|
|
17
17
|
result = ThinkingSphinx::Connection.take do |connection|
|
|
18
|
-
connection.
|
|
18
|
+
connection.execute(statement_for(text)).first['snippet']
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
ThinkingSphinx::UTF8.encode(result)
|
|
21
|
+
encoded? ? result : ThinkingSphinx::UTF8.encode(result)
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
private
|
|
@@ -27,4 +26,9 @@ class ThinkingSphinx::Excerpter
|
|
|
27
26
|
def statement_for(text)
|
|
28
27
|
Riddle::Query.snippets(text, index, words, options)
|
|
29
28
|
end
|
|
29
|
+
|
|
30
|
+
def encoded?
|
|
31
|
+
ThinkingSphinx::Configuration.instance.settings['utf8'].nil? ||
|
|
32
|
+
ThinkingSphinx::Configuration.instance.settings['utf8']
|
|
33
|
+
end
|
|
30
34
|
end
|
|
@@ -105,7 +105,7 @@ class ThinkingSphinx::FacetSearch
|
|
|
105
105
|
", #{ThinkingSphinx::SphinxQL.group_by}, #{ThinkingSphinx::SphinxQL.count}",
|
|
106
106
|
:group_by => facet.name,
|
|
107
107
|
:indices => index_names_for(facet),
|
|
108
|
-
:max_matches =>
|
|
108
|
+
:max_matches => max_matches,
|
|
109
109
|
:limit => limit
|
|
110
110
|
)
|
|
111
111
|
end
|
|
@@ -11,16 +11,12 @@ class ThinkingSphinx::Index
|
|
|
11
11
|
defaults = ThinkingSphinx::Configuration.instance.
|
|
12
12
|
settings['index_options'] || {}
|
|
13
13
|
defaults.symbolize_keys!
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
@reference, @options, @block = reference, defaults.merge(options), block
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def indices
|
|
19
|
-
|
|
20
|
-
delta_indices
|
|
21
|
-
else
|
|
22
|
-
[single_index]
|
|
23
|
-
end
|
|
19
|
+
options[:delta] ? delta_indices : [single_index]
|
|
24
20
|
end
|
|
25
21
|
|
|
26
22
|
private
|
|
@@ -19,8 +19,10 @@ class ThinkingSphinx::IndexSet
|
|
|
19
19
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
|
+
attr_reader :classes, :configuration, :index_names
|
|
23
|
+
|
|
22
24
|
def classes_and_ancestors
|
|
23
|
-
@classes_and_ancestors ||=
|
|
25
|
+
@classes_and_ancestors ||= classes.collect { |model|
|
|
24
26
|
model.ancestors.take_while { |klass|
|
|
25
27
|
klass != ActiveRecord::Base
|
|
26
28
|
}.select { |klass|
|
|
@@ -30,15 +32,15 @@ class ThinkingSphinx::IndexSet
|
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def indices
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return @configuration.indices.select { |index|
|
|
36
|
-
@index_names.include?(index.name)
|
|
37
|
-
} if @index_names && @index_names.any?
|
|
35
|
+
configuration.preload_indices
|
|
38
36
|
|
|
39
|
-
return
|
|
37
|
+
return configuration.indices.select { |index|
|
|
38
|
+
index_names.include?(index.name)
|
|
39
|
+
} if index_names && index_names.any?
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
everything = classes.empty? ? configuration.indices :
|
|
42
|
+
configuration.indices_for_references(*references)
|
|
43
|
+
everything.reject &:distributed?
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def references
|
|
@@ -15,7 +15,6 @@ module ThinkingSphinx::Middlewares
|
|
|
15
15
|
DEFAULT = ::Middleware::Builder.new do
|
|
16
16
|
use StaleIdFilter
|
|
17
17
|
ThinkingSphinx::Middlewares.use self, BASE_MIDDLEWARES
|
|
18
|
-
use UTF8
|
|
19
18
|
use ActiveRecordTranslator
|
|
20
19
|
use StaleIdChecker
|
|
21
20
|
use Glazier
|
|
@@ -23,7 +22,6 @@ module ThinkingSphinx::Middlewares
|
|
|
23
22
|
|
|
24
23
|
RAW_ONLY = ::Middleware::Builder.new do
|
|
25
24
|
ThinkingSphinx::Middlewares.use self, BASE_MIDDLEWARES
|
|
26
|
-
use UTF8
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
IDS_ONLY = ::Middleware::Builder.new do
|
|
@@ -69,6 +69,7 @@ class ThinkingSphinx::Middlewares::ActiveRecordTranslator <
|
|
|
69
69
|
relation = relation.joins sql_options[:joins] if sql_options[:joins]
|
|
70
70
|
relation = relation.order sql_options[:order] if sql_options[:order]
|
|
71
71
|
relation = relation.select sql_options[:select] if sql_options[:select]
|
|
72
|
+
relation = relation.group sql_options[:group] if sql_options[:group]
|
|
72
73
|
relation
|
|
73
74
|
end
|
|
74
75
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
class ThinkingSphinx::Middlewares::SphinxQL <
|
|
2
2
|
ThinkingSphinx::Middlewares::Middleware
|
|
3
3
|
|
|
4
|
-
SELECT_OPTIONS = [:
|
|
5
|
-
:
|
|
6
|
-
:
|
|
7
|
-
:sort_method]
|
|
4
|
+
SELECT_OPTIONS = [:agent_query_timeout, :boolean_simplify, :comment, :cutoff,
|
|
5
|
+
:field_weights, :global_idf, :idf, :index_weights, :max_matches,
|
|
6
|
+
:max_query_time, :max_predicted_time, :ranker, :retry_count, :retry_delay,
|
|
7
|
+
:reverse_scan, :sort_method]
|
|
8
8
|
|
|
9
9
|
def call(contexts)
|
|
10
10
|
contexts.each do |context|
|
|
@@ -197,7 +197,7 @@ SQL
|
|
|
197
197
|
end
|
|
198
198
|
|
|
199
199
|
def scope_by_values
|
|
200
|
-
query.values values
|
|
200
|
+
query.values(values.present? ? values : '*')
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
def scope_by_extended_query
|
|
@@ -225,8 +225,10 @@ SQL
|
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
def scope_by_group
|
|
228
|
-
query.group_by group_attribute
|
|
228
|
+
query.group_by group_attribute if group_attribute.present?
|
|
229
|
+
query.group_best options[:group_best] if options[:group_best]
|
|
229
230
|
query.order_within_group_by group_order_clause if group_order_clause.present?
|
|
231
|
+
query.having options[:having] if options[:having]
|
|
230
232
|
end
|
|
231
233
|
|
|
232
234
|
def scope_by_pagination
|
|
@@ -5,13 +5,18 @@ class ThinkingSphinx::Middlewares::UTF8 <
|
|
|
5
5
|
contexts.each do |context|
|
|
6
6
|
context[:results].each { |row| update_row row }
|
|
7
7
|
update_row context[:meta]
|
|
8
|
-
end unless
|
|
8
|
+
end unless encoded?
|
|
9
9
|
|
|
10
10
|
app.call contexts
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
private
|
|
14
14
|
|
|
15
|
+
def encoded?
|
|
16
|
+
ThinkingSphinx::Configuration.instance.settings['utf8'].nil? ||
|
|
17
|
+
ThinkingSphinx::Configuration.instance.settings['utf8']
|
|
18
|
+
end
|
|
19
|
+
|
|
15
20
|
def update_row(row)
|
|
16
21
|
row.each do |key, value|
|
|
17
22
|
next unless value.is_a?(String)
|
|
@@ -7,16 +7,3 @@ class ThinkingSphinx::Railtie < Rails::Railtie
|
|
|
7
7
|
load File.expand_path('../tasks.rb', __FILE__)
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
|
-
|
|
11
|
-
# Add 'app/indices' path to Rails Engines
|
|
12
|
-
module ThinkingSphinx::EnginePaths
|
|
13
|
-
extend ActiveSupport::Concern
|
|
14
|
-
|
|
15
|
-
included do
|
|
16
|
-
initializer :add_indices_path do
|
|
17
|
-
paths.add "app/indices"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
Rails::Engine.send :include, ThinkingSphinx::EnginePaths
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
|
|
3
2
|
class ThinkingSphinx::Search::Query
|
|
4
|
-
DEFAULT_TOKEN = /[\p{Word}\\][\p{Word}\\@]+/
|
|
5
|
-
|
|
6
3
|
attr_reader :keywords, :conditions, :star
|
|
7
4
|
|
|
8
5
|
def initialize(keywords = '', conditions = {}, star = false)
|
|
@@ -20,24 +17,9 @@ class ThinkingSphinx::Search::Query
|
|
|
20
17
|
private
|
|
21
18
|
|
|
22
19
|
def star_keyword(keyword, key = nil)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
end
|
|
20
|
+
return keyword.to_s unless star
|
|
21
|
+
return keyword.to_s if key.to_s == 'sphinx_internal_class_name'
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
keyword.gsub(/("#{token}(.*?#{token})?"|(?![!-])#{token})/u) do
|
|
29
|
-
pre, proper, post = $`, $&, $'
|
|
30
|
-
# E.g. "@foo", "/2", "~3", but not as part of a token
|
|
31
|
-
is_operator = pre.match(%r{\A(\W|^)[@~/]\Z}) ||
|
|
32
|
-
pre.match(%r{(\W|^)@\([^\)]*$})
|
|
33
|
-
# E.g. "foo bar", with quotes
|
|
34
|
-
is_quote = proper[/^".*"$/]
|
|
35
|
-
has_star = post[/\*$/] || pre[/^\*/]
|
|
36
|
-
if is_operator || is_quote || has_star
|
|
37
|
-
proper
|
|
38
|
-
else
|
|
39
|
-
"*#{proper}*"
|
|
40
|
-
end
|
|
41
|
-
end
|
|
23
|
+
ThinkingSphinx::Query.wildcard keyword, star
|
|
42
24
|
end
|
|
43
25
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class ThinkingSphinx::Wildcard
|
|
2
|
+
DEFAULT_TOKEN = /\p{Word}+/
|
|
3
|
+
|
|
4
|
+
def self.call(query, pattern = DEFAULT_TOKEN)
|
|
5
|
+
new(query, pattern).call
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize(query, pattern = DEFAULT_TOKEN)
|
|
9
|
+
@query = query || ''
|
|
10
|
+
@pattern = pattern.is_a?(Regexp) ? pattern : DEFAULT_TOKEN
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
query.gsub(/("#{pattern}(.*?#{pattern})?"|(?![!-])#{pattern})/u) do
|
|
15
|
+
pre, proper, post = $`, $&, $'
|
|
16
|
+
# E.g. "@foo", "/2", "~3", but not as part of a token pattern
|
|
17
|
+
is_operator = pre == '@' ||
|
|
18
|
+
pre.match(%r{([^\\]+|\A)[~/]\Z}) ||
|
|
19
|
+
pre.match(%r{(\W|^)@\([^\)]*$})
|
|
20
|
+
# E.g. "foo bar", with quotes
|
|
21
|
+
is_quote = proper[/^".*"$/]
|
|
22
|
+
has_star = post[/\*$/] || pre[/^\*/]
|
|
23
|
+
if is_operator || is_quote || has_star
|
|
24
|
+
proper
|
|
25
|
+
else
|
|
26
|
+
"*#{proper}*"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :query, :pattern
|
|
34
|
+
end
|
|
@@ -36,4 +36,17 @@ describe 'Searching by latitude and longitude', :live => true do
|
|
|
36
36
|
cities.first.geodist.should == 250326.906250
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
it "handles custom select clauses that refer to the distance" do
|
|
41
|
+
mel = City.create :name => 'Melbourne', :lat => -0.6599720, :lng => 2.530082
|
|
42
|
+
syd = City.create :name => 'Sydney', :lat => -0.5909679, :lng => 2.639131
|
|
43
|
+
bri = City.create :name => 'Brisbane', :lat => -0.4794031, :lng => 2.670838
|
|
44
|
+
index
|
|
45
|
+
|
|
46
|
+
City.search(
|
|
47
|
+
:geo => [-0.616241, 2.602712],
|
|
48
|
+
:with => {:geodist => 0.0..470_000.0},
|
|
49
|
+
:select => "*, geodist as custom_weight"
|
|
50
|
+
).to_a.should == [mel, syd]
|
|
51
|
+
end
|
|
39
52
|
end
|