datastax_rails 1.0.15 → 1.0.16.3
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.
- data/lib/datastax_rails/collection.rb +4 -0
- data/lib/datastax_rails/connection.rb +43 -7
- data/lib/datastax_rails/cql/base.rb +0 -1
- data/lib/datastax_rails/cql/update.rb +28 -26
- data/lib/datastax_rails/grouped_collection.rb +8 -0
- data/lib/datastax_rails/persistence.rb +4 -0
- data/lib/datastax_rails/railtie.rb +2 -1
- data/lib/datastax_rails/relation/search_methods.rb +120 -32
- data/lib/datastax_rails/relation/spawn_methods.rb +31 -6
- data/lib/datastax_rails/relation.rb +30 -9
- data/lib/datastax_rails/rsolr_client_wrapper.rb +1 -1
- data/lib/datastax_rails/tasks/column_family.rb +38 -11
- data/lib/datastax_rails/tasks/keyspace.rb +1 -1
- data/lib/datastax_rails/types/binary_type.rb +2 -0
- data/lib/datastax_rails/types/date_type.rb +1 -0
- data/lib/datastax_rails/types/string_type.rb +1 -2
- data/lib/datastax_rails/types/time_type.rb +1 -0
- data/lib/datastax_rails/version.rb +1 -1
- data/lib/datastax_rails.rb +1 -1
- data/spec/datastax_rails/relation/search_methods_spec.rb +44 -1
- data/spec/datastax_rails/validations/uniqueness_spec.rb +2 -2
- data/spec/dummy/config/datastax.yml +29 -22
- data/spec/dummy/config/datastax_rails.crt +18 -0
- data/spec/dummy/config/datastax_rails.key +15 -0
- data/spec/dummy/log/development.log +3 -0
- data/spec/dummy/log/test.log +2637 -0
- metadata +17 -24
@@ -1,5 +1,9 @@
|
|
1
1
|
module DatastaxRails
|
2
2
|
class Collection < Array
|
3
|
+
# @!attribute [r] total_entries
|
4
|
+
# @return [Fixnum] the total number of entries that match the search
|
5
|
+
# @!attribute [r] last_column_name
|
6
|
+
# @return [Fixnum] the last column that was returned in the search in case you limited the number of columns (not supported)
|
3
7
|
attr_accessor :last_column_name, :total_entries
|
4
8
|
|
5
9
|
def inspect
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# require 'datastax_rails/rsolr_client_wrapper'
|
2
|
+
require 'rsolr/client_cert'
|
3
|
+
require 'rest_client'
|
2
4
|
module DatastaxRails
|
3
5
|
# The connection module holds all the code for establishing and maintaining a connection to
|
4
6
|
# Datastax Exterprise. This includes both the Cassandra and Solr connections.
|
@@ -13,7 +15,8 @@ module DatastaxRails
|
|
13
15
|
module ClassMethods
|
14
16
|
DEFAULT_OPTIONS = {
|
15
17
|
:servers => "127.0.0.1:9160",
|
16
|
-
:thrift => {}
|
18
|
+
:thrift => {},
|
19
|
+
:cql_version => '3.0.0'
|
17
20
|
}
|
18
21
|
|
19
22
|
# Returns the current server that we are talking to. This is useful when you are talking to a
|
@@ -48,6 +51,11 @@ module DatastaxRails
|
|
48
51
|
# solr:
|
49
52
|
# port: 8983
|
50
53
|
# path: /solr
|
54
|
+
# ssl:
|
55
|
+
# use_ssl: true
|
56
|
+
# cert: config/datastax_rails.crt
|
57
|
+
# key: config/datastax_rails.key
|
58
|
+
# keypass: changeme
|
51
59
|
#
|
52
60
|
# The +servers+ entry should be a list of all of the servers in your local datacenter. These
|
53
61
|
# are the servers that DSR will attempt to connect to and will round-robin through.
|
@@ -85,26 +93,54 @@ module DatastaxRails
|
|
85
93
|
DatastaxRails::Base.config = spec.with_indifferent_access
|
86
94
|
spec.reverse_merge!(DEFAULT_OPTIONS)
|
87
95
|
connection_options = spec[:connection_options] || {}
|
88
|
-
self.connection = CassandraCQL::Database.new(spec[:servers], {:keyspace => spec[:keyspace]}, connection_options.symbolize_keys)
|
96
|
+
self.connection = CassandraCQL::Database.new(spec[:servers], {:keyspace => spec[:keyspace], :cql_version => spec[:cql_version]}, connection_options.symbolize_keys)
|
89
97
|
end
|
90
98
|
|
91
99
|
# Returns the base portion of the URL for connecting to SOLR based on the current Cassandra server.
|
92
100
|
#
|
93
101
|
# @return [String] in the form of 'http://localhost:8983/solr'
|
94
102
|
def solr_base_url
|
95
|
-
DatastaxRails::Base.establish_connection unless self.connection
|
103
|
+
DatastaxRails::Base.establish_connection unless self.connection
|
96
104
|
port = DatastaxRails::Base.config[:solr][:port]
|
97
105
|
path = DatastaxRails::Base.config[:solr][:path]
|
98
|
-
|
106
|
+
protocol = DatastaxRails::Base.config[:solr].has_key?(:ssl) && DatastaxRails::Base.config[:solr][:ssl][:use_ssl] ? 'https' : 'http'
|
107
|
+
"#{protocol}://#{self.current_server}:#{port}#{path}"
|
108
|
+
end
|
109
|
+
|
110
|
+
# Wraps and caches a solr connection object
|
111
|
+
#
|
112
|
+
# @params [Boolean] reconnect force a new connection
|
113
|
+
# @return [DatastaxRails::RSolrClientWrapper] a wrapped RSolr connection
|
114
|
+
def solr_connection(reconnect = false)
|
115
|
+
if(!@rsolr || reconnect)
|
116
|
+
@rsolr = DatastaxRails::RSolrClientWrapper.new(establish_solr_connection)
|
117
|
+
end
|
118
|
+
@rsolr
|
99
119
|
end
|
100
120
|
|
101
121
|
# Similar to +establish_connection+, this method creates a connection object for Solr. Since HTTP is stateless, this doesn't
|
102
122
|
# actually launch the connection, but it gets everything set up so that RSolr can do its work. It's important to note that
|
103
123
|
# unlike the cassandra connection which is global to all of DSR, each model will have its own solr_connection.
|
104
124
|
#
|
105
|
-
# @return [
|
106
|
-
def
|
107
|
-
|
125
|
+
# @return [RSolr::Client] RSolr client object
|
126
|
+
def establish_solr_connection
|
127
|
+
opts = {:url => "#{solr_base_url}/#{DatastaxRails::Base.connection.keyspace}.#{self.column_family}"}
|
128
|
+
if DatastaxRails::Base.config[:solr].has_key?(:ssl) &&
|
129
|
+
DatastaxRails::Base.config[:solr][:ssl].has_key?(:cert) &&
|
130
|
+
DatastaxRails::Base.config[:solr][:ssl][:use_ssl]
|
131
|
+
cert = Pathname.new(DatastaxRails::Base.config[:solr][:ssl][:cert])
|
132
|
+
key = Pathname.new(DatastaxRails::Base.config[:solr][:ssl][:key])
|
133
|
+
pass = DatastaxRails::Base.config[:solr][:ssl][:keypass]
|
134
|
+
cert = Rails.root.join(cert) unless cert.absolute?
|
135
|
+
key = Rails.root.join(key) unless key.absolute?
|
136
|
+
opts[:ssl_cert_file] = cert.to_s
|
137
|
+
opts[:ssl_key_file] = key.to_s
|
138
|
+
opts[:ssl_key_pass] = pass if pass
|
139
|
+
|
140
|
+
RSolr::ClientCert.connect opts
|
141
|
+
else
|
142
|
+
RSolr.connect opts
|
143
|
+
end
|
108
144
|
end
|
109
145
|
end
|
110
146
|
end
|
@@ -34,38 +34,40 @@ module DatastaxRails
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def to_cql
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if(@ttl)
|
43
|
-
stmt << "AND TTL #{@ttl} "
|
44
|
-
end
|
45
|
-
|
46
|
-
if(@timestamp)
|
47
|
-
stmt << "AND TIMESTAMP #{@timestamp}"
|
48
|
-
end
|
49
|
-
|
50
|
-
unless columns.empty?
|
51
|
-
stmt << "SET "
|
37
|
+
column_names = @columns.keys
|
38
|
+
cql = ""
|
39
|
+
Tempfile.open('cql', Rails.root.join("tmp")) do |stmt|
|
40
|
+
stmt << "update #{@klass.column_family} using consistency #{@consistency} "
|
52
41
|
|
53
|
-
|
42
|
+
if(@ttl)
|
43
|
+
stmt << "AND TTL #{@ttl} "
|
44
|
+
end
|
54
45
|
|
55
|
-
|
56
|
-
|
46
|
+
if(@timestamp)
|
47
|
+
stmt << "AND TIMESTAMP #{@timestamp}"
|
48
|
+
end
|
57
49
|
|
58
|
-
columns.
|
59
|
-
stmt << "
|
60
|
-
|
50
|
+
unless @columns.empty?
|
51
|
+
stmt << "SET "
|
52
|
+
|
53
|
+
first_entry = column_names.first
|
54
|
+
|
55
|
+
stmt << CassandraCQL::Statement.sanitize("#{first_entry.to_s} = ?", [@columns[first_entry]])
|
56
|
+
column_names[1..-1].each do |col|
|
57
|
+
stmt << CassandraCQL::Statement.sanitize(", #{col.to_s} = ?", [@columns[col]])
|
58
|
+
end
|
61
59
|
end
|
60
|
+
|
61
|
+
stmt << CassandraCQL::Statement.sanitize(" WHERE KEY IN (?)", [@key])
|
62
|
+
stmt.rewind
|
63
|
+
cql = stmt.read
|
62
64
|
end
|
63
|
-
|
64
|
-
stmt << " WHERE KEY IN (?)"
|
65
|
-
values << @key
|
66
|
-
|
67
|
-
CassandraCQL::Statement.sanitize(stmt, values)
|
65
|
+
cql
|
68
66
|
end
|
67
|
+
|
68
|
+
# def execute
|
69
|
+
# puts to_cql.truncate(50)
|
70
|
+
# end
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -1,5 +1,13 @@
|
|
1
1
|
module DatastaxRails
|
2
|
+
# GroupedCollection extends Hash to add some additional metadata. The hash keys will be the values
|
3
|
+
# for the thing that was grouped on. The hash entries point to instances of DatastaxRails::Collection.
|
2
4
|
class GroupedCollection < Hash
|
5
|
+
# @!attribute [r] total_entries
|
6
|
+
# @return [Fixnum] the total number of entries *in the largest group*. This is to allow will_paginate to work properly.
|
7
|
+
# @!attribute [r] total_groups
|
8
|
+
# @return [Fixnum] the total number of groups if the groups were paginated (not supported yet)
|
9
|
+
# @!attribute [r] total_for_all
|
10
|
+
# @return [Fixnum] the total number of entries across all groups that match this search
|
3
11
|
attr_accessor :total_entries, :total_groups, :total_for_all
|
4
12
|
|
5
13
|
def inspect
|
@@ -15,6 +15,9 @@ module DatastaxRails
|
|
15
15
|
# been updated yet with the results. In practice, this should not happen for
|
16
16
|
# records that were created over your connection, but it is possible for other
|
17
17
|
# connections to create records that you can't see yet.
|
18
|
+
#
|
19
|
+
# @param level [Symbol, String] the level to set the consistency at
|
20
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
18
21
|
def consistency(level)
|
19
22
|
level = level.to_s.upcase
|
20
23
|
unless self.valid_consistency?(level)
|
@@ -34,6 +37,8 @@ module DatastaxRails
|
|
34
37
|
#
|
35
38
|
# Note that fulltext searches are NEVER escaped. Use Relation.solr_escape if you
|
36
39
|
# want that done.
|
40
|
+
#
|
41
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
37
42
|
def dont_escape
|
38
43
|
clone.tap do |r|
|
39
44
|
r.escape_value = false
|
@@ -44,6 +49,9 @@ module DatastaxRails
|
|
44
49
|
# a module or a block provided
|
45
50
|
#
|
46
51
|
# The object returned is a relation which can be further extended
|
52
|
+
#
|
53
|
+
# @param modules [Proc] one or more proc objects
|
54
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
47
55
|
def extending(*modules)
|
48
56
|
modules << Module.new(&Proc.new) if block_given?
|
49
57
|
|
@@ -69,6 +77,9 @@ module DatastaxRails
|
|
69
77
|
# 30
|
70
78
|
# end
|
71
79
|
# end
|
80
|
+
#
|
81
|
+
# @param value [String, Fixnum] the number of records to include on a page
|
82
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
72
83
|
def limit(value)
|
73
84
|
clone.tap do |r|
|
74
85
|
r.per_page_value = value.to_i
|
@@ -79,6 +90,9 @@ module DatastaxRails
|
|
79
90
|
# Sets the page number to retrieve
|
80
91
|
#
|
81
92
|
# Model.page(2)
|
93
|
+
#
|
94
|
+
# @param value [String, Fixnum] the page number to retrieve
|
95
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
82
96
|
def page(value)
|
83
97
|
clone.tap do |r|
|
84
98
|
r.page_value = value.to_i
|
@@ -88,6 +102,10 @@ module DatastaxRails
|
|
88
102
|
# WillPaginate compatible method for paginating
|
89
103
|
#
|
90
104
|
# Model.paginate(:page => 2, :per_page => 10)
|
105
|
+
# @param options [Hash] the options to pass to paginate
|
106
|
+
# @option options [String, Fixnum] :page the page number to retrieve
|
107
|
+
# @option options [String, Fixnum] :per_page the number of records to include on a page
|
108
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
91
109
|
def paginate(options = {})
|
92
110
|
options = options.reverse_merge({:page => 1, :per_page => 30})
|
93
111
|
clone.tap do |r|
|
@@ -102,7 +120,7 @@ module DatastaxRails
|
|
102
120
|
# This modifies the behavior of pagination. When using a group, +per_page+ will
|
103
121
|
# specify the number of results returned *for each group*. In addition, +page+
|
104
122
|
# will move all groups forward by one page possibly resulting in some groups
|
105
|
-
#
|
123
|
+
# showing up empty if they have fewer matching entires than others.
|
106
124
|
#
|
107
125
|
# When grouping is being used, the sort values will be used to sort results within
|
108
126
|
# a given group. Any sorting of the groups themselves will need to be handled
|
@@ -115,6 +133,11 @@ module DatastaxRails
|
|
115
133
|
# NOTE: Group names will be lower-cased
|
116
134
|
#
|
117
135
|
# Model.group(:program_id)
|
136
|
+
#
|
137
|
+
# The object the hash entries point to will be a DatastaxRails::Collection
|
138
|
+
#
|
139
|
+
# @param attribute [Symbol, String] the attribute to group by
|
140
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
118
141
|
def group(attribute)
|
119
142
|
return self if attribute.blank?
|
120
143
|
|
@@ -133,6 +156,9 @@ module DatastaxRails
|
|
133
156
|
#
|
134
157
|
# Model.order(:name)
|
135
158
|
# Model.order(:name => :desc)
|
159
|
+
#
|
160
|
+
# @param attribute [Symbol, String, Hash] the attribute to sort by and optionally the direction to sort in
|
161
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
136
162
|
def order(attribute)
|
137
163
|
return self if attribute.blank?
|
138
164
|
|
@@ -184,15 +210,15 @@ module DatastaxRails
|
|
184
210
|
end
|
185
211
|
end
|
186
212
|
|
187
|
-
# Reverses the order of the results
|
213
|
+
# Reverses the order of the results. The following are equivalent:
|
188
214
|
#
|
189
215
|
# Model.order(:name).reverse_order
|
190
|
-
#
|
191
|
-
# Model.order(:name => :desc)
|
216
|
+
# Model.order(:name => :desc)
|
192
217
|
#
|
193
218
|
# Model.order(:name).reverse_order.reverse_order
|
194
|
-
# is equivalent to
|
195
219
|
# Model.order(:name => :asc)
|
220
|
+
#
|
221
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
196
222
|
def reverse_order
|
197
223
|
clone.tap do |r|
|
198
224
|
r.reverse_order_value == !r.reverse_order_value
|
@@ -206,11 +232,14 @@ module DatastaxRails
|
|
206
232
|
# *This only applies to fulltext queries*
|
207
233
|
#
|
208
234
|
# Model.query_parser('disMax').fulltext("john smith")
|
209
|
-
|
210
|
-
|
235
|
+
#
|
236
|
+
# @param parser [String] the parser to use for the fulltext query
|
237
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
238
|
+
def query_parser(parser)
|
239
|
+
return self if parser.blank?
|
211
240
|
|
212
241
|
clone.tap do |r|
|
213
|
-
r.query_parser_value =
|
242
|
+
r.query_parser_value = parser
|
214
243
|
end
|
215
244
|
end
|
216
245
|
|
@@ -221,6 +250,8 @@ module DatastaxRails
|
|
221
250
|
# it becomes available in SOLR is not guaranteed to be insignificant. It's
|
222
251
|
# very possible to insert a new record and not find it when immediately doing
|
223
252
|
# a SOLR search for it.
|
253
|
+
#
|
254
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
224
255
|
def with_solr
|
225
256
|
clone.tap do |r|
|
226
257
|
r.use_solr_value = true
|
@@ -232,7 +263,9 @@ module DatastaxRails
|
|
232
263
|
# cassandra.
|
233
264
|
#
|
234
265
|
# NOTE that this method assumes that you have all the proper secondary indexes
|
235
|
-
# in place before you attempt to use it. If not, you will get an error.
|
266
|
+
# in place before you attempt to use it. If not, you will get an error.
|
267
|
+
#
|
268
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
236
269
|
def with_cassandra
|
237
270
|
clone.tap do |r|
|
238
271
|
r.use_solr_value = false
|
@@ -255,21 +288,43 @@ module DatastaxRails
|
|
255
288
|
# Model.where(:created_at).greater_than(1.day.ago)
|
256
289
|
# Model.where(:age).less_than(65)
|
257
290
|
#
|
291
|
+
# There is an alternate form of specifying greater than/less than queries
|
292
|
+
# that can be done with a single call. This is useful for remote APIs and
|
293
|
+
# such.
|
294
|
+
#
|
295
|
+
# Model.where(:created_at => {:greater_than => 1.day.ago})
|
296
|
+
# Model.where(:age => {:less_than => 65})
|
297
|
+
#
|
258
298
|
# NOTE: Due to the way SOLR handles range queries, all greater/less than
|
259
|
-
#
|
260
|
-
#
|
299
|
+
# queries are actually greater/less than or equal to queries.
|
300
|
+
# There is no way to perform a strictly greater/less than query.
|
301
|
+
#
|
302
|
+
# @param attribute [Symbol, String, Hash] a hash of conditions or a single attribute that will be followed by
|
303
|
+
# greater_than or less_than
|
304
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
261
305
|
def where(attribute)
|
262
306
|
return self if attribute.blank?
|
263
|
-
|
264
307
|
if attribute.is_a?(Symbol)
|
265
308
|
WhereProxy.new(self, attribute)
|
266
309
|
else
|
267
|
-
attributes = attribute.dup
|
268
|
-
attributes.each do |k,v|
|
269
|
-
attributes[k] = solr_format(v)
|
270
|
-
end
|
271
310
|
clone.tap do |r|
|
272
|
-
|
311
|
+
attributes = attribute.dup
|
312
|
+
attributes.each do |k,v|
|
313
|
+
if(v.is_a?(Hash))
|
314
|
+
comp, value = v.first
|
315
|
+
if(comp.to_s == 'greater_than')
|
316
|
+
r.greater_than_values << {k => value}
|
317
|
+
elsif(comp.to_s == 'less_than')
|
318
|
+
r.less_than_values << {k => value}
|
319
|
+
else
|
320
|
+
r.where_values << {k => value}
|
321
|
+
end
|
322
|
+
attributes.delete(k)
|
323
|
+
else
|
324
|
+
attributes[k] = solr_format(v)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
r.where_values << attributes unless attributes.empty?
|
273
328
|
end
|
274
329
|
end
|
275
330
|
end
|
@@ -285,22 +340,37 @@ module DatastaxRails
|
|
285
340
|
# Model.where_not(:group_id => ['1234', '5678'])
|
286
341
|
#
|
287
342
|
# The above would find all models where group id is neither 1234 or 5678.
|
343
|
+
#
|
344
|
+
# @param attribute [Symbol, String, Hash] a hash of conditions or a single attribute that will be followed by
|
345
|
+
# greater_than or less_than
|
346
|
+
# @return [DatastaxRails::Relation, DatastaxRails::SearchMethods::WhereProxy] a new Relation object
|
347
|
+
# or a proxy object if just an attribute was passed
|
288
348
|
def where_not(attribute)
|
289
349
|
return self if attribute.blank?
|
290
350
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
351
|
+
if attribute.is_a?(Symbol)
|
352
|
+
WhereProxy.new(self, attribute, true)
|
353
|
+
else
|
354
|
+
clone.tap do |r|
|
355
|
+
attributes = attribute.dup
|
356
|
+
attributes.each do |k,v|
|
357
|
+
if(v.is_a?(Hash))
|
358
|
+
comp, value = v.first
|
359
|
+
if(comp.to_s == 'greater_than')
|
360
|
+
r.less_than_values << {k => value}
|
361
|
+
elsif(comp.to_s == 'less_than')
|
362
|
+
r.greater_than_values << {k => value}
|
363
|
+
else
|
364
|
+
r.where_not_values << {k => value}
|
365
|
+
end
|
366
|
+
attributes.delete(k)
|
367
|
+
else
|
368
|
+
attributes[k] = solr_format(v)
|
369
|
+
end
|
296
370
|
end
|
297
|
-
|
298
|
-
attributes << {k => solr_format(v)}
|
371
|
+
r.where_not_values << attributes unless attributes.empty?
|
299
372
|
end
|
300
373
|
end
|
301
|
-
clone.tap do |r|
|
302
|
-
r.where_not_values += attributes
|
303
|
-
end
|
304
374
|
end
|
305
375
|
|
306
376
|
# Specifies a full text search string to be processed by SOLR
|
@@ -314,6 +384,12 @@ module DatastaxRails
|
|
314
384
|
#
|
315
385
|
# Model.fulltext("john smith", :fields => [:title])
|
316
386
|
# Model.fulltext("john smith", :hightlight => [:body])
|
387
|
+
#
|
388
|
+
# @param query [String] a fulltext query to pass to solr
|
389
|
+
# @param opts [Hash] an optional options hash to modify the fulltext query
|
390
|
+
# @option opts [Array] :fields list of fields to search instead of the default of all text fields (not-implemented)
|
391
|
+
# @option opts [Array] :highlight list of fields to retrieve highlights for (not-implemented)
|
392
|
+
# @return [DatastaxRails::Relation] a new Relation object
|
317
393
|
def fulltext(query, opts = {})
|
318
394
|
return self if query.blank?
|
319
395
|
|
@@ -367,25 +443,37 @@ module DatastaxRails
|
|
367
443
|
end
|
368
444
|
|
369
445
|
class WhereProxy #:nodoc:
|
370
|
-
def initialize(relation, attribute) #:nodoc:
|
371
|
-
@relation, @attribute = relation, attribute
|
446
|
+
def initialize(relation, attribute, invert = false) #:nodoc:
|
447
|
+
@relation, @attribute, @invert = relation, attribute, invert
|
372
448
|
end
|
373
449
|
|
374
450
|
def equal_to(value) #:nodoc:
|
375
451
|
@relation.clone.tap do |r|
|
376
|
-
|
452
|
+
if @invert
|
453
|
+
r.where_not_values << {@attribute => r.solr_format(value)}
|
454
|
+
else
|
455
|
+
r.where_values << {@attribute => r.solr_format(value)}
|
456
|
+
end
|
377
457
|
end
|
378
458
|
end
|
379
459
|
|
380
460
|
def greater_than(value) #:nodoc:
|
381
461
|
@relation.clone.tap do |r|
|
382
|
-
|
462
|
+
if @invert
|
463
|
+
r.less_than_values << {@attribute => r.solr_format(value)}
|
464
|
+
else
|
465
|
+
r.greater_than_values << {@attribute => r.solr_format(value)}
|
466
|
+
end
|
383
467
|
end
|
384
468
|
end
|
385
469
|
|
386
470
|
def less_than(value) #:nodoc:
|
387
471
|
@relation.clone.tap do |r|
|
388
|
-
|
472
|
+
if @invert
|
473
|
+
r.greater_than_values << {@attribute => r.solr_format(value)}
|
474
|
+
else
|
475
|
+
r.less_than_values << {@attribute => r.solr_format(value)}
|
476
|
+
end
|
389
477
|
end
|
390
478
|
end
|
391
479
|
end
|
@@ -86,20 +86,45 @@ module DatastaxRails
|
|
86
86
|
result
|
87
87
|
end
|
88
88
|
|
89
|
-
VALID_FIND_OPTIONS = [:conditions, :limit, :select, :offset, :order, :group, :page, :per_page]
|
90
|
-
|
91
|
-
|
89
|
+
VALID_FIND_OPTIONS = [:conditions, :limit, :select, :offset, :order, :group, :page, :per_page, :fulltext, :consistency, :with_solr, :with_cassandra, :where, :where_not]
|
90
|
+
# Applies the passed in finder options and returns a new Relation.
|
91
|
+
# Takes any of the options below and calls them on the relation as if they
|
92
|
+
# were methods (+conditions+ is passed to +where+).
|
93
|
+
#
|
94
|
+
# @param [Hash] options the options hash
|
95
|
+
# @option options [Hash] :conditions
|
96
|
+
# @option options [Symbol, String] :consistency
|
97
|
+
# @option options [String] :fulltext
|
98
|
+
# @option options [Symbol, String] :group
|
99
|
+
# @option options [Integer, String] :limit
|
100
|
+
# @option options [Integer, String] :offset
|
101
|
+
# @option options [String, Hash] :order
|
102
|
+
# @option options [Integer, String] :page
|
103
|
+
# @option options [Integer, String] :per_page
|
104
|
+
# @option options [Array] :select
|
105
|
+
# @option options [Hash] :where
|
106
|
+
# @option options [Hash] :where_not
|
107
|
+
# @option options [Boolean] :with_cassandra
|
108
|
+
# @option options [Boolean] :with_solr
|
109
|
+
# @return [DatastaxRails::Relation] relation with all options applied
|
110
|
+
# @raise [ArgumentError] if an invalid option is passed in
|
111
|
+
def apply_finder_options(options)
|
112
|
+
relation = self
|
92
113
|
return relation unless options
|
93
114
|
|
94
115
|
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
95
116
|
finders = options.dup
|
96
117
|
finders.delete_if { |key, value| value.nil? }
|
97
118
|
|
98
|
-
(
|
99
|
-
|
119
|
+
((VALID_FIND_OPTIONS - [:conditions]) & finders.keys).each do |finder|
|
120
|
+
if(finder.to_s =~ /(with_solr|with_cassandra)/)
|
121
|
+
relation = relation.send(finder)
|
122
|
+
else
|
123
|
+
relation = relation.send(finder, finders[finder])
|
124
|
+
end
|
100
125
|
end
|
101
126
|
|
102
|
-
relation = relation.where(finders[:conditions]) if
|
127
|
+
relation = relation.where(finders[:conditions]) if finders.has_key?(:conditions)
|
103
128
|
relation
|
104
129
|
end
|
105
130
|
end
|
@@ -24,7 +24,13 @@ module DatastaxRails
|
|
24
24
|
alias :loaded? :loaded
|
25
25
|
alias :default_scoped? :default_scoped
|
26
26
|
|
27
|
-
|
27
|
+
# Initializes the Relation. Defaults page value to 1, per_page to the class
|
28
|
+
# default, and solr use to true. Everything else gets defaulted to nil or
|
29
|
+
# empty.
|
30
|
+
#
|
31
|
+
# @param [Class] klass the child of DatastaxRails::Base that this relation searches
|
32
|
+
# @param [String, Symbol] column_family the name of the column family this relation searches
|
33
|
+
def initialize(klass, column_family)
|
28
34
|
@klass, @column_family = klass, column_family
|
29
35
|
@loaded = false
|
30
36
|
@results = []
|
@@ -146,12 +152,14 @@ module DatastaxRails
|
|
146
152
|
@results = []
|
147
153
|
end
|
148
154
|
|
149
|
-
|
155
|
+
# Copies will have changes made to the criteria and so need to be reset.
|
156
|
+
def initialize_copy(other)
|
150
157
|
reset
|
151
158
|
@search = nil
|
152
159
|
end
|
153
160
|
|
154
|
-
|
161
|
+
# Performs a deep copy using Marshal when cloning.
|
162
|
+
def clone
|
155
163
|
dup.tap do |r|
|
156
164
|
MULTI_VALUE_METHODS.each do |m|
|
157
165
|
r.send("#{m}_values=", Marshal.load(Marshal.dump(self.send("#{m}_values"))))
|
@@ -210,7 +218,8 @@ module DatastaxRails
|
|
210
218
|
scoping { @klass.create!(*args, &block) }
|
211
219
|
end
|
212
220
|
|
213
|
-
|
221
|
+
# Override respond_to? so that it matches method_missing
|
222
|
+
def respond_to?(method, include_private = false)
|
214
223
|
Array.method_defined?(method) ||
|
215
224
|
@klass.respond_to?(method, include_private) ||
|
216
225
|
super
|
@@ -339,7 +348,7 @@ module DatastaxRails
|
|
339
348
|
params['group.limit'] = @per_page_value
|
340
349
|
params['group.offset'] = (@page_value - 1) * @per_page_value
|
341
350
|
params['group.ngroups'] = 'true'
|
342
|
-
response = rsolr.post('select', :
|
351
|
+
response = rsolr.post('select', :data => params)["grouped"][@group_value.to_s]
|
343
352
|
results.total_groups = response['ngroups'].to_i
|
344
353
|
results.total_for_all = response['matches'].to_i
|
345
354
|
results.total_entries = 0
|
@@ -348,13 +357,18 @@ module DatastaxRails
|
|
348
357
|
results.total_entries = results[group['groupValue']].total_entries if results[group['groupValue']].total_entries > results.total_entries
|
349
358
|
end
|
350
359
|
else
|
351
|
-
response = rsolr.paginate(@page_value, @per_page_value, 'select', :params =>
|
360
|
+
response = rsolr.paginate(@page_value, @per_page_value, 'select', :data => params, :method => :post)["response"]
|
352
361
|
results = parse_docs(response, select_columns)
|
353
362
|
end
|
354
363
|
results
|
355
364
|
end
|
356
365
|
|
357
|
-
|
366
|
+
# Parse out a set of documents and return the results
|
367
|
+
#
|
368
|
+
# @param response [Hash] the response hash from SOLR with a set of documents
|
369
|
+
# @param select_columns [Array] the columns that we actually selected from SOLR
|
370
|
+
#
|
371
|
+
# @return [DatastaxRails::Collection] the resulting collection
|
358
372
|
def parse_docs(response, select_columns)
|
359
373
|
results = DatastaxRails::Collection.new
|
360
374
|
results.total_entries = response['numFound'].to_i
|
@@ -371,6 +385,10 @@ module DatastaxRails
|
|
371
385
|
end
|
372
386
|
protected(:parse_docs)
|
373
387
|
|
388
|
+
# Inspects the results of the search instead of the Relation itself.
|
389
|
+
# Passing true causes the Relation to be inspected.
|
390
|
+
#
|
391
|
+
# @param [Boolean] just_me if true, inspect the Relation, otherwise the results
|
374
392
|
def inspect(just_me = false)
|
375
393
|
just_me ? super() : to_a.inspect
|
376
394
|
end
|
@@ -389,11 +407,14 @@ module DatastaxRails
|
|
389
407
|
@klass.send(:with_scope, self, :overwrite) { yield }
|
390
408
|
end
|
391
409
|
|
392
|
-
|
410
|
+
# Merges all of the where values together into a single hash
|
411
|
+
def where_values_hash
|
393
412
|
where_values.inject({}) { |values,v| values.merge(v) }
|
394
413
|
end
|
395
414
|
|
396
|
-
|
415
|
+
# Creates a scope that includes all of the where values plus anything
|
416
|
+
# that is in +create_with_value+.
|
417
|
+
def scope_for_create
|
397
418
|
@scope_for_create ||= where_values_hash.merge(create_with_value)
|
398
419
|
end
|
399
420
|
|
@@ -10,7 +10,7 @@ module DatastaxRails
|
|
10
10
|
def method_missing(sym, *args, &block)
|
11
11
|
if @rsolr.uri.host != DatastaxRails::Base.current_server
|
12
12
|
@rsolr.uri.host = DatastaxRails::Base.current_server
|
13
|
-
@rsolr =
|
13
|
+
@rsolr = DatastaxRails::Base.establish_solr_connection
|
14
14
|
end
|
15
15
|
@rsolr.__send__(sym, *args, &block)
|
16
16
|
rescue Errno::ECONNREFUSED
|