activesearch 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/activesearch/algolia.rb +4 -2
- data/lib/activesearch/algolia/client.rb +10 -4
- data/lib/activesearch/mongoid.rb +5 -2
- data/lib/activesearch/mongoid/full_text_search_query.rb +86 -0
- data/lib/activesearch/mongoid/index.rb +9 -49
- data/lib/activesearch/version.rb +1 -1
- data/spec/models/mongoid.rb +1 -1
- data/spec/support/setup_engine.rb +5 -0
- data/spec/support/shared_examples_for_engines.rb +14 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad6a5304a892366c29fdaaac5d36acd68c01cccd
|
4
|
+
data.tar.gz: 390657dc4805e5404f5a05ddecd264e20283fb7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 241cd473dcb494c7267864e8976166da68e2a0f13b40a5c9b1b6759167d70ebfa570f8a4c0252d06fd6bca8044088dcca3368188a53aa18993a8c55100d5f0bc
|
7
|
+
data.tar.gz: ad669841f7ea28d1e1f337cdfd1192c945e50d7499e99ae39e18372fa96752e7157d41ef18f24c01e7626f8c6e9b440b2c6bf28e0a31ba8a60d456ee03337ef0
|
data/lib/activesearch/algolia.rb
CHANGED
@@ -10,7 +10,7 @@ module ActiveSearch
|
|
10
10
|
conditions[:locale] ||= locale
|
11
11
|
|
12
12
|
Proxy.new(text, conditions, options) do |text, conditions|
|
13
|
-
Algolia::Client.new.query(text, tags: conditions_to_tags(conditions))["hits"].map! do |hit|
|
13
|
+
Algolia::Client.new.query(text, { tags: conditions_to_tags(conditions) }, options)["hits"].map! do |hit|
|
14
14
|
if hit["_tags"]
|
15
15
|
hit["_tags"].each do |tag|
|
16
16
|
# preserve other ":" characters
|
@@ -49,7 +49,7 @@ module ActiveSearch
|
|
49
49
|
Worker.new.async.perform(task: :deindex, id: self.id, type: self.class.to_s)
|
50
50
|
end
|
51
51
|
|
52
|
-
def to_indexable
|
52
|
+
def to_indexable(depth = 0)
|
53
53
|
{}.tap do |doc|
|
54
54
|
_locale = search_locale
|
55
55
|
|
@@ -57,6 +57,8 @@ module ActiveSearch
|
|
57
57
|
if content = send(field)
|
58
58
|
doc[field.to_s] = if content.is_a?(Hash) && content.has_key?(_locale)
|
59
59
|
ActiveSearch.strip_tags(content[_locale])
|
60
|
+
elsif content && content.respond_to?(:to_indexable)
|
61
|
+
ActiveSearch.strip_tags(content.to_indexable(depth + 1))
|
60
62
|
else
|
61
63
|
ActiveSearch.strip_tags(content)
|
62
64
|
end
|
@@ -5,7 +5,7 @@ module ActiveSearch
|
|
5
5
|
module Algolia
|
6
6
|
class Client
|
7
7
|
include HTTParty
|
8
|
-
|
8
|
+
|
9
9
|
def self.configure(api_key, app_id, index = "activesearch")
|
10
10
|
base_uri "https://#{app_id}.algolia.io/1/indexes/#{index}"
|
11
11
|
headers({
|
@@ -28,10 +28,16 @@ module ActiveSearch
|
|
28
28
|
self.class.put("/#{id}", body: object.to_json)
|
29
29
|
end
|
30
30
|
|
31
|
-
def query(text, extras = {})
|
32
|
-
|
31
|
+
def query(text, extras = {}, options = {})
|
32
|
+
page, per_page = options[:page] || 0, options[:per_page] || 20
|
33
|
+
|
34
|
+
self.class.get('', query: extras.merge!(
|
35
|
+
query: text,
|
36
|
+
page: page,
|
37
|
+
hitsPerPage: per_page
|
38
|
+
))
|
33
39
|
end
|
34
|
-
|
40
|
+
|
35
41
|
def get(id)
|
36
42
|
self.class.get("/#{id}")
|
37
43
|
end
|
data/lib/activesearch/mongoid.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'activesearch/base'
|
2
2
|
require 'activesearch/proxy'
|
3
|
+
require 'activesearch/mongoid/full_text_search_query'
|
3
4
|
require 'activesearch/mongoid/index'
|
4
5
|
|
5
6
|
module ActiveSearch
|
@@ -9,7 +10,7 @@ module ActiveSearch
|
|
9
10
|
conditions[:locale] ||= locale
|
10
11
|
|
11
12
|
Proxy.new(text, conditions, options) do |text, conditions|
|
12
|
-
ActiveSearch::Mongoid::Index.search(text, conditions)
|
13
|
+
ActiveSearch::Mongoid::Index.search(text, conditions, options)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -20,7 +21,7 @@ module ActiveSearch
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
def to_indexable
|
24
|
+
def to_indexable(depth = 0)
|
24
25
|
{}.tap do |doc|
|
25
26
|
_locale = search_locale
|
26
27
|
|
@@ -28,6 +29,8 @@ module ActiveSearch
|
|
28
29
|
if content = send(field)
|
29
30
|
doc[field.to_s] = if content.is_a?(Hash) && content.has_key?(_locale)
|
30
31
|
ActiveSearch.strip_tags(content[_locale])
|
32
|
+
elsif content && content.respond_to?(:to_indexable)
|
33
|
+
ActiveSearch.strip_tags(content.to_indexable(depth + 1))
|
31
34
|
else
|
32
35
|
ActiveSearch.strip_tags(content)
|
33
36
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module ActiveSearch
|
2
|
+
module Mongoid
|
3
|
+
class FullTextSearchQuery
|
4
|
+
|
5
|
+
attr_reader :results
|
6
|
+
|
7
|
+
def initialize(name, query, conditions, options)
|
8
|
+
@name = name
|
9
|
+
@query = query
|
10
|
+
@filter = prepare_filter(conditions)
|
11
|
+
@options = options
|
12
|
+
@language = self.class.locale_to_language(conditions[:locale] || I18n.locale)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
@results = session.command({
|
17
|
+
'text' => @name,
|
18
|
+
'search' => @query,
|
19
|
+
'language' => @language,
|
20
|
+
'filter' => @filter
|
21
|
+
})
|
22
|
+
|
23
|
+
if @results.has_key?('results')
|
24
|
+
sanitize_results
|
25
|
+
else
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def session
|
31
|
+
::Mongoid.session('default')
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.locale_to_language(locale)
|
35
|
+
{
|
36
|
+
dk: 'danish',
|
37
|
+
nl: 'dutch',
|
38
|
+
en: 'english',
|
39
|
+
fi: 'finnish',
|
40
|
+
fr: 'french',
|
41
|
+
de: 'german',
|
42
|
+
hu: 'hungarian',
|
43
|
+
it: 'italian',
|
44
|
+
nb: 'norwegian',
|
45
|
+
br: 'portuguese',
|
46
|
+
pt: 'portuguese',
|
47
|
+
ro: 'romanian',
|
48
|
+
ru: 'russian',
|
49
|
+
es: 'spanish',
|
50
|
+
se: 'swedish',
|
51
|
+
tr: 'turkish'
|
52
|
+
}[locale.to_sym] || 'english'
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def prepare_filter(conditions)
|
58
|
+
{}.tap do |filter|
|
59
|
+
conditions.each do |key, value|
|
60
|
+
if key == :locale
|
61
|
+
filter['locale'] = value.to_s
|
62
|
+
else
|
63
|
+
filter["stored.#{key}"] = value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def sanitize_results
|
70
|
+
page, per_page = @options[:page] || 0, @options[:per_page] || 10
|
71
|
+
included = ((page * per_page)..((page + 1) * per_page - 1))
|
72
|
+
_results = []
|
73
|
+
|
74
|
+
# manual pagination since it is not natively supported by MongoDB
|
75
|
+
@results['results'].each_with_index do |result, index|
|
76
|
+
if included === index
|
77
|
+
_results << result['obj']['stored'].merge(result['obj'].slice('locale', 'original_type', 'original_id'))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
@results = _results
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -21,7 +21,7 @@ module ActiveSearch
|
|
21
21
|
|
22
22
|
def store_language(original)
|
23
23
|
self.locale = original.search_locale
|
24
|
-
self.language =
|
24
|
+
self.language = FullTextSearchQuery.locale_to_language(self.locale)
|
25
25
|
end
|
26
26
|
|
27
27
|
def store_fields(original)
|
@@ -30,8 +30,11 @@ module ActiveSearch
|
|
30
30
|
fields = (original.search_fields + (original.search_options[:store] || [])).uniq
|
31
31
|
|
32
32
|
fields.each do |f|
|
33
|
-
|
34
|
-
|
33
|
+
content = original.send(f)
|
34
|
+
|
35
|
+
if content.present?
|
36
|
+
content = content.to_indexable if content.respond_to?(:to_indexable)
|
37
|
+
self.stored[f] = ActiveSearch.strip_tags(content)
|
35
38
|
end
|
36
39
|
end
|
37
40
|
end
|
@@ -42,32 +45,9 @@ module ActiveSearch
|
|
42
45
|
|
43
46
|
## class methods ##
|
44
47
|
|
45
|
-
def self.search(query, conditions = {})
|
46
|
-
|
47
|
-
|
48
|
-
filter = {}
|
49
|
-
conditions.each do |key, value|
|
50
|
-
if key == :locale
|
51
|
-
filter['locale'] = value.to_s
|
52
|
-
else
|
53
|
-
filter["stored.#{key}"] = value
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
session = ::Mongoid.session('default')
|
58
|
-
results = session.command({
|
59
|
-
'text' => collection.name,
|
60
|
-
'search' => query,
|
61
|
-
'language' => language,
|
62
|
-
'filter' => filter
|
63
|
-
})
|
64
|
-
if results.has_key?('results')
|
65
|
-
results['results'].map do |result|
|
66
|
-
result['obj']['stored'].merge(result['obj'].slice('locale', 'original_type', 'original_id'))
|
67
|
-
end
|
68
|
-
else
|
69
|
-
[]
|
70
|
-
end
|
48
|
+
def self.search(query, conditions = {}, options = {})
|
49
|
+
query = FullTextSearchQuery.new(collection.name, query, conditions, options)
|
50
|
+
query.run
|
71
51
|
end
|
72
52
|
|
73
53
|
def self.deindex(original)
|
@@ -90,26 +70,6 @@ module ActiveSearch
|
|
90
70
|
doc.save
|
91
71
|
end
|
92
72
|
|
93
|
-
def self.locale_to_language(locale)
|
94
|
-
{
|
95
|
-
dk: 'danish',
|
96
|
-
nl: 'dutch',
|
97
|
-
en: 'english',
|
98
|
-
fi: 'finnish',
|
99
|
-
fr: 'french',
|
100
|
-
de: 'german',
|
101
|
-
hu: 'hungarian',
|
102
|
-
it: 'italian',
|
103
|
-
nb: 'norwegian',
|
104
|
-
br: 'portuguese',
|
105
|
-
pt: 'portuguese',
|
106
|
-
ro: 'romanian',
|
107
|
-
ru: 'russian',
|
108
|
-
es: 'spanish',
|
109
|
-
se: 'swedish',
|
110
|
-
tr: 'turkish'
|
111
|
-
}[locale.to_sym] || 'english'
|
112
|
-
end
|
113
73
|
end
|
114
74
|
end
|
115
75
|
end
|
data/lib/activesearch/version.rb
CHANGED
data/spec/models/mongoid.rb
CHANGED
@@ -57,7 +57,20 @@ shared_examples 'an engine' do
|
|
57
57
|
@model.create(title: <<-LIPSUM, junk: "Junk field", scope_id: 1)
|
58
58
|
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy findable text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
|
59
59
|
LIPSUM
|
60
|
-
ActiveSearch.search("dummy findable").first
|
60
|
+
entry = ActiveSearch.search("dummy findable").first
|
61
|
+
entry["highlighted"]["title"].should == "Lorem Ipsum is simply <em>dummy</em> text of the printing and typesetting industry. Lo..."
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should paginate docs" do
|
65
|
+
page = ActiveSearch.search("findable", {}, { page: 0, per_page: 2 })
|
66
|
+
first_page_titles = page.map { |e| e['title'] }
|
67
|
+
page.count.should == 2
|
68
|
+
|
69
|
+
page = ActiveSearch.search("findable", {}, { page: 1, per_page: 2 })
|
70
|
+
second_page_titles = page.map { |e| e['title'] }
|
71
|
+
page.count.should == 2
|
72
|
+
|
73
|
+
first_page_titles.should_not == second_page_titles
|
61
74
|
end
|
62
75
|
|
63
76
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activesearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Alvarez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-04-
|
12
|
+
date: 2014-04-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -203,6 +203,7 @@ files:
|
|
203
203
|
- lib/activesearch/base.rb
|
204
204
|
- lib/activesearch/elastic_search.rb
|
205
205
|
- lib/activesearch/mongoid.rb
|
206
|
+
- lib/activesearch/mongoid/full_text_search_query.rb
|
206
207
|
- lib/activesearch/mongoid/index.rb
|
207
208
|
- lib/activesearch/proxy.rb
|
208
209
|
- lib/activesearch/result.rb
|