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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b24050eefed5b21eb1b0d085fa964effdc06c2d8
4
- data.tar.gz: 780df5ddeb72407c972869ab11a9a6e015018554
3
+ metadata.gz: ad6a5304a892366c29fdaaac5d36acd68c01cccd
4
+ data.tar.gz: 390657dc4805e5404f5a05ddecd264e20283fb7a
5
5
  SHA512:
6
- metadata.gz: c1e5576e03f3f0ae6a610ddef63bf3c661e68520ef8fdae55ca4e98c9676f14fb038de8088b416c59b085515ea4568aa5b58500085003bae87ee80c375e66cc7
7
- data.tar.gz: f1caac8c129064500ec93a3f13f7854ab83f698ed7e27f8729ae9fc21cf2a2a999a23fd75663304590bb1490ef0e979e2f3a2fff4ff7abd71b4aa884eb7e23c1
6
+ metadata.gz: 241cd473dcb494c7267864e8976166da68e2a0f13b40a5c9b1b6759167d70ebfa570f8a4c0252d06fd6bca8044088dcca3368188a53aa18993a8c55100d5f0bc
7
+ data.tar.gz: ad669841f7ea28d1e1f337cdfd1192c945e50d7499e99ae39e18372fa96752e7157d41ef18f24c01e7626f8c6e9b440b2c6bf28e0a31ba8a60d456ee03337ef0
@@ -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
- self.class.get("", query: extras.merge!(query: text))
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
@@ -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 = self.class.locale_to_language(self.locale)
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
- if original.send(f).present?
34
- self.stored[f] = ActiveSearch.strip_tags(original.send(f))
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
- language = self.locale_to_language(conditions[:locale] || I18n.locale)
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
@@ -1,3 +1,3 @@
1
1
  module ActiveSearch
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
@@ -27,7 +27,7 @@ class AnotherMongoidModel
27
27
  end
28
28
 
29
29
  def virtual
30
- "virtual"
30
+ Struct.new(:to_indexable).new('virtual')
31
31
  end
32
32
  end
33
33
 
@@ -41,6 +41,11 @@ module SetupEngine
41
41
 
42
42
  ActiveSearch::Mongoid::Index.create_indexes
43
43
 
44
+ if ENV['MONGOID_LOGS'].present?
45
+ Moped.logger = Logger.new($stdout)
46
+ Moped.logger.level = Logger::DEBUG
47
+ end
48
+
44
49
  DatabaseCleaner.clean
45
50
  end
46
51
 
@@ -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["highlighted"]["title"].should == "Lorem Ipsum is simply <em>dummy</em> text of the printing and typesetting industry. Lo..."
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.0
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-01 00:00:00.000000000 Z
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