Skip to content

Commit

Permalink
Merge upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
DanBradbury committed Feb 18, 2016
2 parents cae2d1a + 3920925 commit 6c5f1f0
Show file tree
Hide file tree
Showing 18 changed files with 693 additions and 334 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
## 1.2.2 [unreleased]

- Added support for phrase matches

## 1.2.1

- Added `multi_search` method
- Added support for routing for Elasticsearch 2
- Added support for `search_document_id` and `search_document_type` in models
- Fixed error with instrumentation for searching multiple models
- Fixed instrumentation for bulk updates

## 1.2.0

- Fixed deprecation warnings with `alias_method_chain`
- Added `analyzed_only` option for large text fields
- Added `encoder` option to highlight
- Fixed issue in `similar` method with `per_page` option
- Added basic support for multiple models

## 1.1.2

- Added bulk updates with `callbacks` method
Expand Down
63 changes: 52 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ Plus:

```sh
brew install elasticsearch

# start the server
elasticsearch
```

Add this line to your application’s Gemfile:
Expand Down Expand Up @@ -244,6 +247,12 @@ Available options are:
User.search params[:q], fields: [{email: :exact}, :name]
```

### Phrase Matches [master]

```ruby
User.search "fresh honey", match: :phrase
```

### Language

Searchkick defaults to English for stemming. To change this, use:
Expand Down Expand Up @@ -335,12 +344,13 @@ Control what data is indexed with the `search_data` method. Call `Product.reinde

```ruby
class Product < ActiveRecord::Base
belongs_to :department

def search_data
as_json only: [:name, :active]
# or equivalently
{
name: name,
active: active
department_name: department.name,
on_sale: sale_price.present?
}
end
end
Expand All @@ -350,7 +360,7 @@ Searchkick uses `find_in_batches` to import documents. To eager load associatio

```ruby
class Product < ActiveRecord::Base
scope :search_import, -> { includes(:searches) }
scope :search_import, -> { includes(:department) }
end
```

Expand Down Expand Up @@ -394,7 +404,7 @@ There are three strategies for keeping the index synced with your database.
end
```

And [install Active Job](https://github.com/ankane/activejob_backport) for Rails 4.1 and below
And [install Active Job](https://github.com/ankane/activejob_backport) for Rails 4.1 and below. Jobs are added to a queue named `searchkick`.

3. Manual

Expand Down Expand Up @@ -830,18 +840,20 @@ City.search "san", boost_by_distance: {field: :location, origin: {lat: 37, lon:

Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/blog/customizing-your-document-routing).

**Note:** Routing is not yet supported for Elasticsearch 2.0.

```ruby
class Contact < ActiveRecord::Base
searchkick routing: :user_id
class Business < ActiveRecord::Base
searchkick routing: true

def search_routing
city_id
end
end
```

Reindex and search with:

```ruby
Contact.search "John", routing: current_user.id
Business.search "ice cream", routing: params[:city_id]
```

## Inheritance
Expand Down Expand Up @@ -958,6 +970,7 @@ gem 'faraday_middleware-aws-signers-v4'
and add to your initializer:

```ruby
require "faraday_middleware/aws_signers_v4"
Searchkick.client =
Elasticsearch::Client.new(
url: ENV["ELASTICSEARCH_URL"],
Expand Down Expand Up @@ -1085,6 +1098,20 @@ products =
end
```

### Multi Search

To batch search requests for performance, use:

```ruby
fresh_products = Product.search("fresh", execute: false)
frozen_products = Product.search("frozen", execute: false)
Searchkick.multi_search([fresh_products, frozen_products])
```

Then use `fresh_products` and `frozen_products` as typical results.

**Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors. Also, if you use the `below` option for misspellings, misspellings will be disabled.

## Reference

Reindex one record
Expand Down Expand Up @@ -1121,6 +1148,14 @@ Remove old indices
Product.clean_indices
```

Use custom settings

```ruby
class Product < ActiveRecord::Base
searchkick settings: {number_of_shards: 3}
end
```

Use a different index name

```ruby
Expand Down Expand Up @@ -1223,7 +1258,7 @@ end

Reindex conditionally

**Note:** With ActiveRecord, use this feature with caution - [transaction rollbacks can cause data inconstencies](https://github.com/elasticsearch/elasticsearch-rails/blob/master/elasticsearch-model/README.md#custom-callbacks)
**Note:** With ActiveRecord, use this feature with caution - [transaction rollbacks can cause data inconsistencies](https://github.com/elasticsearch/elasticsearch-rails/blob/master/elasticsearch-model/README.md#custom-callbacks)

```ruby
class Product < ActiveRecord::Base
Expand All @@ -1235,6 +1270,12 @@ class Product < ActiveRecord::Base
end
```

Search multiple models

```ruby
Searchkick.search "milk", index_name: [Product, Category]
```

Reindex all models - Rails only

```sh
Expand Down
22 changes: 21 additions & 1 deletion lib/searchkick.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
require "searchkick/model"
require "searchkick/tasks"
require "searchkick/middleware"
require "searchkick/logging" if defined?(Rails)
require "searchkick/logging" if defined?(ActiveSupport::Notifications)

# background jobs
begin
Expand Down Expand Up @@ -133,6 +133,26 @@ def self.callbacks_value
def self.callbacks_value=(value)
Thread.current[:searchkick_callbacks_enabled] = value
end

def self.search(term = nil, options = {}, &block)
query = Searchkick::Query.new(nil, term, options)
block.call(query.body) if block
if options[:execute] == false
query
else
query.execute
end
end

def self.multi_search(queries)
if queries.any?
responses = client.msearch(body: queries.flat_map { |q| [q.params.except(:body), q.body] })["responses"]
queries.each_with_index do |query, i|
query.handle_response(responses[i])
end
end
nil
end
end

# TODO find better ActiveModel hook
Expand Down
37 changes: 30 additions & 7 deletions lib/searchkick/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,24 @@ def remove(record)
end

def bulk_delete(records)
Searchkick.queue_items(records.reject { |r| r.id.blank? }.map { |r| {delete: {_index: name, _type: document_type(r), _id: search_id(r)}} })
Searchkick.queue_items(records.reject { |r| r.id.blank? }.map { |r| {delete: record_data(r)} })
end

def bulk_index(records)
Searchkick.queue_items(records.map { |r| {index: {_index: name, _type: document_type(r), _id: search_id(r), data: search_data(r)}} })
Searchkick.queue_items(records.map { |r| {index: record_data(r).merge(data: search_data(r))} })
end
alias_method :import, :bulk_index

def record_data(r)
data = {
_index: name,
_id: search_id(r),
_type: document_type(r)
}
data[:_routing] = r.search_routing if r.respond_to?(:search_routing)
data
end

def retrieve(record)
client.get(
index: name,
Expand Down Expand Up @@ -102,7 +112,7 @@ def similar_record(record, options = {})
options[:where] ||= {}
options[:where][:_id] ||= {}
options[:where][:_id][:not] = record.id.to_s
options[:limit] ||= 10
options[:per_page] ||= 10
options[:similar] = true

# TODO use index class instead of record class
Expand Down Expand Up @@ -132,7 +142,12 @@ def create_index(options = {})

# remove old indices that start w/ index_name
def clean_indices
all_indices = client.indices.get_aliases
all_indices =
begin
client.indices.get_aliases
rescue Elasticsearch::Transport::Transport::Errors::NotFound
[]
end
indices = all_indices.select { |k, v| (v.empty? || v["aliases"].empty?) && k =~ /\A#{Regexp.escape(name)}_\d{14,17}\z/ }.keys
indices.each do |index|
Searchkick::Index.new(index).delete
Expand Down Expand Up @@ -458,7 +473,10 @@ def index_options

routing = {}
if options[:routing]
routing = {required: true, path: options[:routing].to_s}
routing = {required: true}
unless options[:routing] == true
routing[:path] = options[:routing].to_s
end
end

dynamic_fields = {
Expand Down Expand Up @@ -528,11 +546,16 @@ def client
end

def document_type(record)
klass_document_type(record.class)
if record.respond_to?(:search_document_type)
record.search_document_type
else
klass_document_type(record.class)
end
end

def search_id(record)
record.id.is_a?(Numeric) ? record.id : record.id.to_s
id = record.respond_to?(:search_document_id) ? record.search_document_id : record.id
id.is_a?(Numeric) ? id : id.to_s
end

def search_data(record)
Expand Down
Loading

0 comments on commit 6c5f1f0

Please sign in to comment.