Class: Elastic
- Inherits:
-
Object
- Object
- Elastic
- Defined in:
- lib/co-elastic-query.rb
Defined Under Namespace
Classes: Query
Constant Summary collapse
- HOST =
if ENV['ELASTIC'] ENV['ELASTIC'].split(' ').map {|item| "#{item}:9200"} else ['localhost:9200'] end
- COUNT =
'count'.freeze
- HITS =
'hits'.freeze
- TOTAL =
'total'.freeze
- ID =
'_id'.freeze
- SCORE =
['_score'.freeze]
- INDEX =
(ENV['ELASTIC_INDEX'] || 'default').freeze
Class Method Summary collapse
Instance Method Summary collapse
- #count(builder) ⇒ Object
- #generate_body(builder) ⇒ Object
-
#initialize(klass = nil, **opts) ⇒ Elastic
constructor
A new instance of Elastic.
-
#query(params = nil, filters = nil) ⇒ Object
Safely build the query.
- #search(builder, &block) ⇒ Object
Constructor Details
#initialize(klass = nil, **opts) ⇒ Elastic
Returns a new instance of Elastic.
322 323 324 325 326 327 328 329 |
# File 'lib/co-elastic-query.rb', line 322 def initialize(klass = nil, **opts) if klass @klass = klass @filter = klass.design_document end @index = opts[:index] || INDEX @use_couch_type = opts[:use_couch_type] || false end |
Class Method Details
.client ⇒ Object
307 308 309 |
# File 'lib/co-elastic-query.rb', line 307 def self.client @@client end |
.count(*args) ⇒ Object
303 304 305 |
# File 'lib/co-elastic-query.rb', line 303 def self.count *args @@client.count *args end |
.new_client ⇒ Object
311 312 313 |
# File 'lib/co-elastic-query.rb', line 311 def self.new_client @@client = Elasticsearch::Client.new hosts: HOST, reload_connections: true, adapter: :libuv end |
.search(*args) ⇒ Object
299 300 301 |
# File 'lib/co-elastic-query.rb', line 299 def self.search *args @@client.search *args end |
Instance Method Details
#count(builder) ⇒ Object
368 369 370 371 372 373 374 375 376 377 |
# File 'lib/co-elastic-query.rb', line 368 def count(builder) query = generate_body(builder) # Simplify the query query[:body].delete(:from) query[:body].delete(:size) query[:body].delete(:sort) Elastic.count(query)[COUNT] end |
#generate_body(builder) ⇒ Object
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/co-elastic-query.rb', line 380 def generate_body(builder) opt = builder.build sort = (opt[:sort] || []) + SCORE queries = opt[:queries] || [] queries.unshift(opt[:query]) filters = opt[:filters] || [] if @filter if @use_couch_type filters.unshift({term: {'doc.type' => @filter}}) else filters.unshift({type: {value: @filter}}) end end { index: @index, body: { sort: sort, query: { bool: { must: { query: { bool: { must: queries } } }, filter: { bool: { must: filters } } } }, from: opt[:offset], size: opt[:limit] } } end |
#query(params = nil, filters = nil) ⇒ Object
Safely build the query
332 333 334 335 336 |
# File 'lib/co-elastic-query.rb', line 332 def query(params = nil, filters = nil) builder = ::Elastic::Query.new(params) builder.filter(filters) if filters builder end |
#search(builder, &block) ⇒ Object
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/co-elastic-query.rb', line 338 def search(builder, &block) query = generate_body(builder) # if a formatter block is supplied, each loaded record is passed to it # allowing annotation/conversion of records using data from the model # and current request (e.g groups are annotated with 'admin' if the # currently logged in user is an admin of the group). nils are removed # from the list. result = Elastic.search(query) records = if @klass Array(@klass.find_by_id(result[HITS][HITS].map {|entry| entry[ID]})) else Array(result[HITS][HITS].map { |entry| ::CouchbaseOrm.try_load(entry[ID]) }).compact end results = block_given? ? (records.map {|record| yield record}).compact : records # Ensure the total is accurate total = result[HITS][TOTAL] || 0 total = total - (records.length - results.length) # adjust for compaction # We check records against limit (pre-compaction) and total against actual result length # Worst case senario is there is one additional request for results at an offset that returns no results. # The total results number will be accurate on the final page of results from the clients perspective. total = results.length + builder.offset if records.length < builder.limit && total > (results.length + builder.offset) { total: total, results: results } end |