Skip to content

Commit 7638e03

Browse files
committed
Add support for analytics rules
1 parent 7d2f0a4 commit 7638e03

8 files changed

Lines changed: 188 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Tests are also a good place to know how the the library works internally: [spec]
3333

3434
| Typesense Server | typesense-ruby |
3535
|------------------|----------------|
36+
| \>= v0.25.0 | \>= v0.15.0 |
3637
| \>= v0.23.0 | \>= v0.14.0 |
3738
| \>= v0.21.0 | \>= v0.13.0 |
3839
| \>= v0.20.0 | \>= v0.12.0 |

lib/typesense.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ module Typesense
2020
require_relative 'typesense/keys'
2121
require_relative 'typesense/key'
2222
require_relative 'typesense/multi_search'
23+
require_relative 'typesense/analytics'
24+
require_relative 'typesense/analytics_rule'
25+
require_relative 'typesense/analytics_rules'
2326
require_relative 'typesense/debug'
2427
require_relative 'typesense/health'
2528
require_relative 'typesense/metrics'

lib/typesense/analytics.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
module Typesense
4+
class Analytics
5+
RESOURCE_PATH = '/analytics'
6+
7+
def initialize(api_call)
8+
@api_call = api_call
9+
end
10+
11+
def rules
12+
@rules ||= AnalyticsRules.new(@api_call)
13+
end
14+
end
15+
end

lib/typesense/analytics_rule.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module Typesense
4+
class AnalyticsRule
5+
def initialize(rule_name, api_call)
6+
@rule_name = rule_name
7+
@api_call = api_call
8+
end
9+
10+
def retrieve
11+
@api_call.get(endpoint_path)
12+
end
13+
14+
def delete
15+
@api_call.delete(endpoint_path)
16+
end
17+
18+
private
19+
20+
def endpoint_path
21+
"#{AnalyticsRules::RESOURCE_PATH}/#{@rule_name}"
22+
end
23+
end
24+
end

lib/typesense/analytics_rules.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
module Typesense
4+
class AnalyticsRules
5+
RESOURCE_PATH = '/analytics/rules'
6+
7+
def initialize(api_call)
8+
@api_call = api_call
9+
@analytics_rules = {}
10+
end
11+
12+
def upsert(rule_name, params)
13+
@api_call.put(endpoint_path(rule_name), params)
14+
end
15+
16+
def retrieve
17+
@api_call.get(endpoint_path)
18+
end
19+
20+
def [](rule_name)
21+
@analytics_rules[rule_name] ||= AnalyticsRule.new(rule_name, @api_call)
22+
end
23+
24+
private
25+
26+
def endpoint_path(operation = nil)
27+
"#{AnalyticsRules::RESOURCE_PATH}#{operation.nil? ? '' : "/#{operation}"}"
28+
end
29+
end
30+
end

lib/typesense/client.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Typesense
44
class Client
55
attr_reader :configuration, :collections, :aliases, :keys, :debug, :health, :metrics, :operations,
6-
:multi_search
6+
:multi_search, :analytics
77

88
def initialize(options = {})
99
@configuration = Configuration.new(options)
@@ -16,6 +16,7 @@ def initialize(options = {})
1616
@health = Health.new(@api_call)
1717
@metrics = Metrics.new(@api_call)
1818
@operations = Operations.new(@api_call)
19+
@analytics = Analytics.new(@api_call)
1920
end
2021
end
2122
end
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../spec_helper'
4+
require_relative 'shared_configuration_context'
5+
6+
describe Typesense::AnalyticsRule do
7+
subject(:analytics_rule) { typesense.analytics.rules['search_suggestions'] }
8+
9+
include_context 'with Typesense configuration'
10+
11+
let(:analytics_rule_data) do
12+
{
13+
'name' => 'search_suggestions',
14+
'type' => 'popular_queries',
15+
'params' => {
16+
'source' => { 'collections' => ['products'] },
17+
'destination' => { 'collection' => 'products_top_queries' },
18+
'limit' => 100
19+
}
20+
}
21+
end
22+
23+
describe '#retrieve' do
24+
it 'returns the specified analytics rule' do
25+
stub_request(:get, Typesense::ApiCall.new(typesense.configuration).send(:uri_for, '/analytics/rules/search_suggestions', typesense.configuration.nodes[0]))
26+
.with(headers: {
27+
'X-Typesense-Api-Key' => typesense.configuration.api_key,
28+
'Content-Type': 'application/json'
29+
})
30+
.to_return(status: 200, body: JSON.dump(analytics_rule_data), headers: { 'Content-Type': 'application/json' })
31+
32+
result = analytics_rule.retrieve
33+
34+
expect(result).to eq(analytics_rule_data)
35+
end
36+
end
37+
38+
describe '#delete' do
39+
it 'deletes the specified analytics rule' do
40+
stub_request(:delete, Typesense::ApiCall.new(typesense.configuration).send(:uri_for, '/analytics/rules/search_suggestions', typesense.configuration.nodes[0]))
41+
.with(headers: {
42+
'X-Typesense-Api-Key' => typesense.configuration.api_key
43+
})
44+
.to_return(status: 200, body: JSON.dump('name' => 'search_suggestions'), headers: { 'Content-Type': 'application/json' })
45+
46+
result = analytics_rule.delete
47+
48+
expect(result).to eq('name' => 'search_suggestions')
49+
end
50+
end
51+
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
require_relative '../spec_helper'
4+
require_relative 'shared_configuration_context'
5+
6+
describe Typesense::AnalyticsRules do
7+
subject(:analytics_rules) { typesense.analytics.rules }
8+
9+
include_context 'with Typesense configuration'
10+
11+
let(:analytics_rule) do
12+
{
13+
'name' => 'search_suggestions',
14+
'type' => 'popular_queries',
15+
'params' => {
16+
'source' => { 'collections' => ['products'] },
17+
'destination' => { 'collection' => 'products_top_queries' },
18+
'limit' => 100
19+
}
20+
}
21+
end
22+
23+
describe '#upsert' do
24+
it 'creates a rule and returns it' do
25+
stub_request(:put, Typesense::ApiCall.new(typesense.configuration).send(:uri_for, '/analytics/rules/search_suggestions', typesense.configuration.nodes[0]))
26+
.with(body: analytics_rule,
27+
headers: {
28+
'X-Typesense-Api-Key' => typesense.configuration.api_key,
29+
'Content-Type' => 'application/json'
30+
})
31+
.to_return(status: 201, body: JSON.dump(analytics_rule), headers: { 'Content-Type': 'application/json' })
32+
33+
result = typesense.analytics.rules.upsert(analytics_rule['name'], analytics_rule)
34+
35+
expect(result).to eq(analytics_rule)
36+
end
37+
end
38+
39+
describe '#retrieve' do
40+
it 'retrieves all analytics rules' do
41+
stub_request(:get, Typesense::ApiCall.new(typesense.configuration).send(:uri_for, '/analytics/rules', typesense.configuration.nodes[0]))
42+
.with(headers: {
43+
'X-Typesense-Api-Key' => typesense.configuration.api_key,
44+
'Content-Type' => 'application/json'
45+
})
46+
.to_return(status: 201, body: JSON.dump([analytics_rule]), headers: { 'Content-Type': 'application/json' })
47+
48+
result = analytics_rules.retrieve
49+
50+
expect(result).to eq([analytics_rule])
51+
end
52+
end
53+
54+
describe '#[]' do
55+
it 'creates an analytics rule object and returns it' do
56+
result = analytics_rules['search_suggestions']
57+
58+
expect(result).to be_a_kind_of(Typesense::AnalyticsRule)
59+
expect(result.instance_variable_get(:@rule_name)).to eq('search_suggestions')
60+
end
61+
end
62+
end

0 commit comments

Comments
 (0)