model_set 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rbenv-gemsets +1 -0
- data/.rbenv-version +1 -0
- data/Gemfile +3 -0
- data/Rakefile +2 -39
- data/VERSION +1 -1
- data/lib/model_set/conditioned.rb +14 -15
- data/lib/model_set/conditions.rb +26 -33
- data/lib/model_set/query.rb +16 -12
- data/lib/model_set/solr_query.rb +40 -30
- data/lib/model_set/sphinx_query.rb +89 -43
- data/lib/model_set/sql_base_query.rb +27 -15
- data/lib/model_set/sql_query.rb +8 -10
- data/lib/model_set.rb +39 -15
- data/model_set.gemspec +24 -136
- data/test/model_set_test.rb +18 -0
- data/test/test_helper.rb +1 -6
- data/vendor/sphinx_client/lib/sphinx/client.rb +68 -18
- data/vendor/sphinx_client/lib/sphinx/response.rb +68 -68
- data/vendor/sphinx_client/spec/client_spec.rb +4 -4
- data/vendor/sphinx_client/spec/fixtures/keywords.php +7 -7
- data/vendor/sphinx_client/spec/fixtures/sphinxapi.php +5 -3
- data/vendor/sphinx_client/spec/sphinx/sphinx-id64.conf +1 -1
- data/vendor/sphinx_client/spec/sphinx/sphinx.conf +1 -1
- data/vendor/sphinx_client/test.rb +27 -0
- metadata +131 -24
data/.gitignore
ADDED
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
model_set
|
data/.rbenv-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ree-1.8.7-2012.02
|
data/Gemfile
ADDED
data/Rakefile
CHANGED
@@ -1,47 +1,10 @@
|
|
1
|
-
require 'rake'
|
2
1
|
require 'rake/testtask'
|
3
|
-
require '
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'jeweler'
|
7
|
-
Jeweler::Tasks.new do |s|
|
8
|
-
s.name = "model_set"
|
9
|
-
s.summary = %Q{Easy manipulation of sets of ActiveRecord models}
|
10
|
-
s.email = "code@justinbalthrop.com"
|
11
|
-
s.homepage = "http://github.com/ninjudd/model_set"
|
12
|
-
s.description = "Easy manipulation of sets of ActiveRecord models"
|
13
|
-
s.authors = ["Justin Balthrop"]
|
14
|
-
s.add_dependency('ordered_set', '>= 1.0.1')
|
15
|
-
s.add_dependency('deep_clonable', '>= 1.1.0')
|
16
|
-
s.add_dependency('activerecord', '>= 2.0.0')
|
17
|
-
end
|
18
|
-
Jeweler::GemcutterTasks.new
|
19
|
-
rescue LoadError
|
20
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
21
|
-
end
|
2
|
+
require 'bundler/gem_tasks'
|
22
3
|
|
23
4
|
Rake::TestTask.new do |t|
|
24
|
-
t.libs
|
5
|
+
t.libs = ['lib']
|
25
6
|
t.pattern = 'test/**/*_test.rb'
|
26
7
|
t.verbose = false
|
27
8
|
end
|
28
9
|
|
29
|
-
Rake::RDocTask.new do |rdoc|
|
30
|
-
rdoc.rdoc_dir = 'rdoc'
|
31
|
-
rdoc.title = 'model_set'
|
32
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
33
|
-
rdoc.rdoc_files.include('README*')
|
34
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
35
|
-
end
|
36
|
-
|
37
|
-
begin
|
38
|
-
require 'rcov/rcovtask'
|
39
|
-
Rcov::RcovTask.new do |t|
|
40
|
-
t.libs << 'test'
|
41
|
-
t.test_files = FileList['test/**/*_test.rb']
|
42
|
-
t.verbose = true
|
43
|
-
end
|
44
|
-
rescue LoadError
|
45
|
-
end
|
46
|
-
|
47
10
|
task :default => :test
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
@@ -2,28 +2,27 @@ class ModelSet
|
|
2
2
|
module Conditioned
|
3
3
|
# Shared methods for dealing with conditions.
|
4
4
|
attr_accessor :conditions
|
5
|
-
|
6
|
-
def add_conditions!(*conditions)
|
7
|
-
operator = conditions.shift if conditions.first.kind_of?(Symbol)
|
8
|
-
operator ||= :and
|
9
5
|
|
10
|
-
|
11
|
-
conditions.
|
12
|
-
condition.kind_of?(Conditions) ? condition : Conditions.new( sanitize_condition(condition) )
|
13
|
-
end
|
6
|
+
def add_conditions!(*conditions)
|
7
|
+
new_conditions = conditions.first.kind_of?(Symbol) ? [conditions.shift] : []
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
conditions.each do |condition|
|
10
|
+
if condition.kind_of?(Conditions)
|
11
|
+
new_conditions << condition
|
12
|
+
else
|
13
|
+
new_conditions.concat([*transform_condition(condition)])
|
14
|
+
end
|
19
15
|
end
|
16
|
+
return self if new_conditions.empty?
|
20
17
|
|
21
|
-
conditions
|
22
|
-
@conditions = Conditions.new(operator, *conditions)
|
23
|
-
|
18
|
+
@conditions = to_conditions(*new_conditions) << @conditions
|
24
19
|
clear_cache!
|
25
20
|
end
|
26
21
|
|
22
|
+
def to_conditions(*conditions)
|
23
|
+
Conditions.new(conditions, condition_ops)
|
24
|
+
end
|
25
|
+
|
27
26
|
def invert!
|
28
27
|
raise 'cannot invert without conditions' if @conditions.nil?
|
29
28
|
@conditions = ~@conditions
|
data/lib/model_set/conditions.rb
CHANGED
@@ -4,40 +4,27 @@ class ModelSet
|
|
4
4
|
|
5
5
|
attr_reader :operator, :conditions
|
6
6
|
|
7
|
-
def self.new(*args)
|
8
|
-
if args.size == 1 and args.first.kind_of?(self)
|
9
|
-
# Just clone if the only argument is a Conditions object.
|
10
|
-
args.first.clone
|
11
|
-
elsif args.size == 2 and [:and, :or].include?(args.first)
|
12
|
-
# The operator is not necessary if there is only one subcondition.
|
13
|
-
new(args.last)
|
14
|
-
else
|
15
|
-
super
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
7
|
def new(*args)
|
20
8
|
self.class.new(*args)
|
21
9
|
end
|
22
10
|
|
23
|
-
def initialize(
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if operator == :not
|
32
|
-
raise "unary operator :not cannot have multiple conditions" if args.size > 1
|
33
|
-
@conditions = [self.class.new(args.first)]
|
11
|
+
def initialize(conditions, ops)
|
12
|
+
@ops = ops
|
13
|
+
if conditions.kind_of?(Array)
|
14
|
+
@operator = conditions.first.kind_of?(Symbol) ? conditions.shift : :and
|
15
|
+
if @operator == :not
|
16
|
+
# In this case, :not actually means :and :not.
|
17
|
+
@conditions = ~Conditions.new([:and, conditions], @ops)
|
34
18
|
else
|
19
|
+
raise "invalid operator :#{operator}" unless [:and, :or].include?(@operator)
|
35
20
|
# Compact the conditions if possible.
|
36
21
|
@conditions = []
|
37
|
-
|
22
|
+
conditions.each do |clause|
|
38
23
|
self << clause
|
39
24
|
end
|
40
25
|
end
|
26
|
+
else
|
27
|
+
@conditions = [conditions]
|
41
28
|
end
|
42
29
|
end
|
43
30
|
|
@@ -46,15 +33,17 @@ class ModelSet
|
|
46
33
|
end
|
47
34
|
|
48
35
|
def <<(clause)
|
36
|
+
return self unless clause
|
49
37
|
raise 'cannot append conditions to a terminal' if terminal?
|
50
|
-
|
51
|
-
clause =
|
38
|
+
|
39
|
+
clause = new(clause, @ops) unless clause.kind_of?(Conditions)
|
52
40
|
if clause.operator == operator
|
53
41
|
@conditions.concat(clause.conditions)
|
54
42
|
else
|
55
43
|
@conditions << clause
|
56
44
|
end
|
57
45
|
@conditions.uniq!
|
46
|
+
self
|
58
47
|
end
|
59
48
|
|
60
49
|
def ~
|
@@ -73,20 +62,24 @@ class ModelSet
|
|
73
62
|
new(:and, self, other)
|
74
63
|
end
|
75
64
|
|
65
|
+
def op(type)
|
66
|
+
@ops[type]
|
67
|
+
end
|
68
|
+
|
76
69
|
def to_s
|
77
|
-
return conditions.first if terminal?
|
70
|
+
return conditions.first.to_s if terminal? or conditions.empty?
|
78
71
|
|
79
72
|
condition_strings = conditions.collect do |condition|
|
80
73
|
condition.operator == :not ? condition.to_s : "(#{condition.to_s})"
|
81
74
|
end.sort_by {|s| s.size}
|
82
75
|
|
83
76
|
case operator
|
84
|
-
when :not
|
85
|
-
"
|
86
|
-
when :and
|
87
|
-
"#{condition_strings.join(
|
88
|
-
when :or
|
89
|
-
"#{condition_strings.join(
|
77
|
+
when :not then
|
78
|
+
"#{op(:not)} #{condition_strings.first}"
|
79
|
+
when :and then
|
80
|
+
"#{condition_strings.join(op(:and))}"
|
81
|
+
when :or then
|
82
|
+
"#{condition_strings.join(op(:or))}"
|
90
83
|
end
|
91
84
|
end
|
92
85
|
|
data/lib/model_set/query.rb
CHANGED
@@ -37,27 +37,28 @@ class ModelSet
|
|
37
37
|
@page = nil if offset
|
38
38
|
clear_limited_cache!
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def unlimited!
|
42
42
|
@limit = nil
|
43
43
|
@offset = nil
|
44
44
|
@page = nil
|
45
45
|
clear_limited_cache!
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def clear_limited_cache!
|
49
49
|
@ids = nil
|
50
50
|
@size = nil
|
51
51
|
self
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def clear_cache!
|
55
55
|
@count = nil
|
56
56
|
clear_limited_cache!
|
57
57
|
end
|
58
58
|
|
59
|
-
attr_reader :set_class
|
60
|
-
delegate :id_field,
|
59
|
+
attr_reader :set_class, :limit, :sort_order
|
60
|
+
delegate :id_field, :to => :set_class
|
61
|
+
delegate :id_field_with_prefix, :to => :set_class
|
61
62
|
|
62
63
|
def model_class
|
63
64
|
set_class.query_model_class
|
@@ -71,12 +72,6 @@ class ModelSet
|
|
71
72
|
model_class.table_name
|
72
73
|
end
|
73
74
|
|
74
|
-
def id_field_with_prefix
|
75
|
-
"#{table_name}.#{id_field}"
|
76
|
-
end
|
77
|
-
|
78
|
-
attr_reader :limit, :sort_order
|
79
|
-
|
80
75
|
def offset
|
81
76
|
if limit
|
82
77
|
@offset ||= @page ? (@page - 1) * limit : 0
|
@@ -97,7 +92,7 @@ class ModelSet
|
|
97
92
|
proc = self.class.before_query
|
98
93
|
proc.bind(self).call(*args) if proc
|
99
94
|
end
|
100
|
-
|
95
|
+
|
101
96
|
def self.before_query(&block)
|
102
97
|
if block
|
103
98
|
@before_query = block
|
@@ -132,5 +127,14 @@ class ModelSet
|
|
132
127
|
end
|
133
128
|
end
|
134
129
|
|
130
|
+
def condition_ops
|
131
|
+
{ :not => 'NOT ',
|
132
|
+
:and => ' AND ',
|
133
|
+
:or => ' OR ' }
|
134
|
+
end
|
135
|
+
|
136
|
+
def transform_condition(condition)
|
137
|
+
[condition]
|
138
|
+
end
|
135
139
|
end
|
136
140
|
end
|
data/lib/model_set/solr_query.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
|
-
require '
|
1
|
+
require 'rsolr'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
class ModelSet
|
4
5
|
class SolrQuery < Query
|
5
|
-
attr_reader :response
|
6
6
|
include Conditioned
|
7
7
|
|
8
8
|
MAX_SOLR_RESULTS = 1000
|
9
9
|
|
10
|
+
class << self
|
11
|
+
attr_accessor :host
|
12
|
+
end
|
13
|
+
attr_reader :response
|
14
|
+
|
10
15
|
def anchor!(query)
|
11
16
|
add_conditions!( ids_clause(query.ids) )
|
12
|
-
end
|
17
|
+
end
|
13
18
|
|
14
19
|
def size
|
15
20
|
fetch_results if @size.nil?
|
@@ -26,41 +31,50 @@ class ModelSet
|
|
26
31
|
@ids
|
27
32
|
end
|
28
33
|
|
29
|
-
def
|
30
|
-
@
|
34
|
+
def use_core!(core)
|
35
|
+
@core = core
|
31
36
|
end
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
query = "#{conditions.to_s}"
|
37
|
-
solr_params = {:highlighting => {}}
|
38
|
+
def solr_params!(opts)
|
39
|
+
@opts = opts
|
40
|
+
end
|
38
41
|
|
39
|
-
|
40
|
-
|
42
|
+
def id_field
|
43
|
+
if set_class.respond_to?(:solr_id_field)
|
44
|
+
set_class.solr_id_field
|
45
|
+
else
|
46
|
+
'id'
|
41
47
|
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
42
51
|
|
52
|
+
def fetch_results
|
53
|
+
params = @opts || {}
|
54
|
+
params[:q] = "#{conditions.to_s}"
|
55
|
+
params[:fl] ||= [id_field]
|
56
|
+
params[:fl] = params[:fl].join(",")
|
57
|
+
params[:wt] = :json
|
43
58
|
if limit
|
44
|
-
|
45
|
-
|
59
|
+
params[:rows] = limit
|
60
|
+
params[:start] = offset
|
46
61
|
else
|
47
|
-
|
62
|
+
params[:rows] = MAX_SOLR_RESULTS
|
48
63
|
end
|
49
64
|
|
50
|
-
before_query(
|
51
|
-
begin
|
52
|
-
|
53
|
-
if @
|
54
|
-
|
55
|
-
|
56
|
-
@response = Solr::Connection.new(solr_uri).search(query, solr_params)
|
65
|
+
before_query(params)
|
66
|
+
begin
|
67
|
+
url = "http://" + self.class.host
|
68
|
+
url += "/" + @core if @core
|
69
|
+
search = RSolr.connect(:url => url)
|
70
|
+
@response = JSON.parse(search.get('select', :params => params))
|
57
71
|
rescue Exception => e
|
58
|
-
on_exception(e,
|
72
|
+
on_exception(e, params)
|
59
73
|
end
|
60
|
-
after_query(
|
74
|
+
after_query(params)
|
61
75
|
|
62
|
-
@count =
|
63
|
-
@ids =
|
76
|
+
@count = response['response']['numFound']
|
77
|
+
@ids = response['response']['docs'].collect {|doc| set_class.as_id(doc[id_field])}.to_ordered_set
|
64
78
|
@size = @ids.size
|
65
79
|
end
|
66
80
|
|
@@ -69,9 +83,5 @@ class ModelSet
|
|
69
83
|
field ||= 'pk_i'
|
70
84
|
"#{field}:(#{ids.join(' OR ')})"
|
71
85
|
end
|
72
|
-
|
73
|
-
def sanitize_condition(condition)
|
74
|
-
condition
|
75
|
-
end
|
76
86
|
end
|
77
87
|
end
|
@@ -1,20 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../vendor/sphinx_client/lib/sphinx'
|
2
|
-
|
3
|
-
require 'system_timer'
|
4
|
-
rescue LoadError => e
|
5
|
-
module SystemTimer
|
6
|
-
def self.timeout(time, &block)
|
7
|
-
Timeout.timeout(time, &block)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
2
|
+
require 'system_timer'
|
11
3
|
|
12
4
|
class ModelSet
|
13
5
|
class SphinxQuery < Query
|
14
|
-
|
15
|
-
MAX_QUERY_TIME = 5
|
6
|
+
include Conditioned
|
16
7
|
|
17
|
-
|
8
|
+
MAX_RESULTS = 1000
|
9
|
+
MAX_QUERY_TIME = 5
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :host, :port
|
13
|
+
end
|
14
|
+
attr_reader :filters, :response
|
18
15
|
|
19
16
|
def max_query_time
|
20
17
|
@max_query_time || MAX_QUERY_TIME
|
@@ -24,6 +21,14 @@ class ModelSet
|
|
24
21
|
@max_query_time = seconds
|
25
22
|
end
|
26
23
|
|
24
|
+
def max_results
|
25
|
+
@max_results || MAX_RESULTS
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_results!(max)
|
29
|
+
@max_results = max
|
30
|
+
end
|
31
|
+
|
27
32
|
def anchor!(query)
|
28
33
|
add_filters!( id_field => query.ids.to_a )
|
29
34
|
end
|
@@ -43,28 +48,20 @@ class ModelSet
|
|
43
48
|
@geo = opts
|
44
49
|
end
|
45
50
|
|
46
|
-
def add_conditions!(conditions)
|
47
|
-
if conditions.kind_of?(Hash)
|
48
|
-
conditions.each do |field, value|
|
49
|
-
next if value.nil?
|
50
|
-
field = field.join(',') if field.kind_of?(Array)
|
51
|
-
value = "(#{value.join('|')})" if value.kind_of?(Array)
|
52
|
-
add_conditions!("@(#{field}) #{value}")
|
53
|
-
end
|
54
|
-
else
|
55
|
-
@conditions ||= []
|
56
|
-
@conditions << conditions
|
57
|
-
@conditions.uniq!
|
58
|
-
clear_cache!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
51
|
def index
|
63
52
|
@index ||= '*'
|
64
53
|
end
|
65
54
|
|
66
|
-
def use_index!(index)
|
67
|
-
|
55
|
+
def use_index!(index, opts = {})
|
56
|
+
if opts[:delta]
|
57
|
+
@index = "#{index} #{index}_delta"
|
58
|
+
else
|
59
|
+
@index = index
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def select_fields!(*fields)
|
64
|
+
@select = fields.flatten
|
68
65
|
end
|
69
66
|
|
70
67
|
SORT_MODES = {
|
@@ -72,7 +69,7 @@ class ModelSet
|
|
72
69
|
:descending => Sphinx::Client::SPH_SORT_ATTR_DESC,
|
73
70
|
:ascending => Sphinx::Client::SPH_SORT_ATTR_ASC,
|
74
71
|
:time => Sphinx::Client::SPH_SORT_TIME_SEGMENTS,
|
75
|
-
:
|
72
|
+
:extended => Sphinx::Client::SPH_SORT_EXTENDED,
|
76
73
|
:expression => Sphinx::Client::SPH_SORT_EXPR,
|
77
74
|
}
|
78
75
|
|
@@ -86,6 +83,27 @@ class ModelSet
|
|
86
83
|
clear_cache!
|
87
84
|
end
|
88
85
|
|
86
|
+
RANKING_MODES = {
|
87
|
+
:proximity_bm25 => Sphinx::Client::SPH_RANK_PROXIMITY_BM25,
|
88
|
+
:bm25 => Sphinx::Client::SPH_RANK_BM25,
|
89
|
+
:none => Sphinx::Client::SPH_RANK_NONE,
|
90
|
+
:word_count => Sphinx::Client::SPH_RANK_WORDCOUNT,
|
91
|
+
:proximity => Sphinx::Client::SPH_RANK_PROXIMITY,
|
92
|
+
:fieldmask => Sphinx::Client::SPH_RANK_FIELDMASK,
|
93
|
+
:sph04 => Sphinx::Client::SPH_RANK_SPH04,
|
94
|
+
:total => Sphinx::Client::SPH_RANK_TOTAL,
|
95
|
+
}
|
96
|
+
|
97
|
+
def rank_using!(mode_or_expr)
|
98
|
+
if mode_or_expr.nil?
|
99
|
+
@ranking = nil
|
100
|
+
elsif mode = RANKING_MODES[mode_or_expr]
|
101
|
+
@ranking = [mode]
|
102
|
+
else
|
103
|
+
@ranking = [Sphinx::Client::SPH_RANK_EXPR, mode_or_expr]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
89
107
|
def size
|
90
108
|
fetch_results if @size.nil?
|
91
109
|
@size
|
@@ -96,11 +114,23 @@ class ModelSet
|
|
96
114
|
@count
|
97
115
|
end
|
98
116
|
|
117
|
+
def total_count
|
118
|
+
response['total_found']
|
119
|
+
end
|
120
|
+
|
99
121
|
def ids
|
100
122
|
fetch_results if @ids.nil?
|
101
123
|
@ids
|
102
124
|
end
|
103
125
|
|
126
|
+
def id_field
|
127
|
+
if set_class.respond_to?(:sphinx_id_field)
|
128
|
+
set_class.sphinx_id_field
|
129
|
+
else
|
130
|
+
'id'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
104
134
|
class SphinxError < StandardError
|
105
135
|
attr_accessor :opts
|
106
136
|
def message
|
@@ -111,28 +141,30 @@ class ModelSet
|
|
111
141
|
private
|
112
142
|
|
113
143
|
def fetch_results
|
114
|
-
if
|
144
|
+
if conditions.nil? or @empty
|
115
145
|
@count = 0
|
116
146
|
@size = 0
|
117
147
|
@ids = []
|
118
148
|
else
|
119
149
|
opts = {
|
120
150
|
:filters => @filters,
|
121
|
-
:query =>
|
151
|
+
:query => conditions.to_s,
|
122
152
|
}
|
123
153
|
before_query(opts)
|
124
154
|
|
125
155
|
search = Sphinx::Client.new
|
126
156
|
search.SetMaxQueryTime(max_query_time * 1000)
|
127
|
-
search.SetServer(self.class.
|
157
|
+
search.SetServer(self.class.host, self.class.port)
|
158
|
+
search.SetSelect((@select || [id_field]).join(','))
|
128
159
|
search.SetMatchMode(Sphinx::Client::SPH_MATCH_EXTENDED2)
|
129
160
|
if limit
|
130
|
-
search.SetLimits(offset, limit,
|
161
|
+
search.SetLimits(offset, limit, max_results)
|
131
162
|
else
|
132
|
-
search.SetLimits(0,
|
163
|
+
search.SetLimits(0, max_results, max_results)
|
133
164
|
end
|
134
165
|
|
135
166
|
search.SetSortMode(*@sort_order) if @sort_order
|
167
|
+
search.SetRankingMode(*@ranking) if @ranking
|
136
168
|
search.SetFilter('class_id', model_class.class_id) if model_class.respond_to?(:class_id)
|
137
169
|
|
138
170
|
if @geo
|
@@ -161,7 +193,7 @@ class ModelSet
|
|
161
193
|
end
|
162
194
|
|
163
195
|
begin
|
164
|
-
response = SystemTimer.timeout(max_query_time) do
|
196
|
+
@response = SystemTimer.timeout(max_query_time) do
|
165
197
|
search.Query(opts[:query], index)
|
166
198
|
end
|
167
199
|
unless response
|
@@ -175,8 +207,8 @@ class ModelSet
|
|
175
207
|
on_exception(e)
|
176
208
|
end
|
177
209
|
|
178
|
-
@count = response['total_found']
|
179
|
-
@ids = response['matches'].collect {|
|
210
|
+
@count = [response['total_found'], max_results].min
|
211
|
+
@ids = response['matches'].collect {|match| set_class.as_id(match[id_field])}.to_ordered_set
|
180
212
|
@size = @ids.size
|
181
213
|
|
182
214
|
after_query(opts)
|
@@ -195,12 +227,26 @@ class ModelSet
|
|
195
227
|
end
|
196
228
|
end
|
197
229
|
|
198
|
-
|
199
|
-
|
230
|
+
def condition_ops
|
231
|
+
{ :not => '-',
|
232
|
+
:and => ' ',
|
233
|
+
:or => '|' }
|
200
234
|
end
|
201
235
|
|
202
|
-
def
|
203
|
-
|
236
|
+
def transform_condition(condition)
|
237
|
+
if condition.kind_of?(Hash)
|
238
|
+
condition.collect do |field, value|
|
239
|
+
next if value.nil?
|
240
|
+
field = field.join(',') if field.kind_of?(Array)
|
241
|
+
if value.kind_of?(Array)
|
242
|
+
value = [:or, *value] unless value.first.kind_of?(Symbol)
|
243
|
+
value = to_conditions(*value).to_s
|
244
|
+
end
|
245
|
+
"@(#{field}) #{value}"
|
246
|
+
end.compact
|
247
|
+
else
|
248
|
+
condition
|
249
|
+
end
|
204
250
|
end
|
205
251
|
end
|
206
252
|
end
|