redi_searcher 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3970933331248a4f4eaf439a12dc2f035dad533bcc62ee0d0b758162a969f649
4
+ data.tar.gz: 152d010d2d7296910b4a579035c8c9d2ee1784e561a229d392a8d4e0fbe84f62
5
+ SHA512:
6
+ metadata.gz: 7163297b6dcc1e15e48ca2648d436262768d7807aade7161a588ac6e4939dd3474886e77d498f6474bc9e8caa0ade0d0a0822304a4bcd0693170c8dc5b64a510
7
+ data.tar.gz: fab6459bba1d28528727c6ec6794fe53065dd0b778f5f9cc8ea1e776fcdc89a2693dc0e0a0e6f0e4f6bc5334c9a07eea266e377220886bb99cd9329d54b86bd2
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # Ignore all files with the .gem extension
11
+ *.gem
@@ -0,0 +1,20 @@
1
+ require 'redi_searcher/client'
2
+ require 'redi_searcher/client/command_base'
3
+
4
+ require 'redi_searcher/schema'
5
+ require 'redi_searcher/schema/field'
6
+
7
+ require 'redi_searcher/index'
8
+ require 'redi_searcher/document'
9
+
10
+
11
+
12
+ module RediSearcher
13
+ DEFAULT_WEIGHT = '1.0'
14
+
15
+ class << self
16
+ def client
17
+ @client ||= Client.new
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module RediSearcher
2
+ class Client
3
+
4
+ def initialize(redis = {}, *args)
5
+ @redis = Redis.new(redis)
6
+ end
7
+
8
+ def generate_index(name, schema)
9
+ RediSearcher::Index.new(self, name, schema)
10
+ end
11
+
12
+ def call(command)
13
+ raise ArgumentError.new("unknown/unsupported command '#{command.first}'") unless valid_command?(command.first)
14
+ with_reconnect { @redis.call(command.flatten) }
15
+ end
16
+
17
+ # return true or false
18
+ def multi
19
+ with_reconnect { @redis.multi { yield } }
20
+ end
21
+
22
+ private
23
+
24
+ attr_accessor :redis
25
+
26
+ def with_reconnect
27
+ @redis.with_reconnect { yield }
28
+ end
29
+
30
+ def valid_command?(command)
31
+ %w(FT.CREATE FT.ADD FT.ADDHASH FT.SEARCH FT.DEL FT.DROP FT.GET FT.MGET
32
+ FT.SUGADD FT.SUGGET FT.SUGDEL FT.SUGLEN FT.SYNADD FT.SYNUPDATE FT.SYNDUMP
33
+ FT.INFO FT.AGGREGATE FT.EXPLAIN FT.TAGVALS FT.CONFIG).include?(command)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module RediSearcher
2
+ class Client
3
+ class CommandBase
4
+ OPTIONS_FLAGS = {}
5
+ OPTIONS_PARAMS = {}
6
+
7
+ private
8
+
9
+ def serialize_options(method, **options)
10
+ [flags_for_method(method, options), params_for_method(method, options)].flatten.compact
11
+ end
12
+
13
+ def flags_for_method(method, **options)
14
+ self.class::OPTIONS_FLAGS[method].to_a.map do |key|
15
+ key.to_s.upcase if options[key]
16
+ end.compact
17
+ end
18
+
19
+ def params_for_method(method, **options)
20
+ self.class::OPTIONS_PARAMS[method].to_a.map do |key|
21
+ [key.to_s.upcase, *options[key]] unless options[key].nil?
22
+ end.compact
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,46 @@
1
+ module RediSearcher
2
+ class Document < Client::CommandBase
3
+ OPTIONS_FLAGS = {
4
+ add: [:nosave, :replace, :partial],
5
+ del: [:dd]
6
+ }
7
+
8
+ OPTIONS_PARAMS = {
9
+ add: [:language, :payload],
10
+ }
11
+
12
+ attr_reader :index, :doc_id, :fields, :weight
13
+
14
+ def initialize(index, doc_id, weight = nil, **fields)
15
+ @index = index
16
+ @doc_id = doc_id
17
+ @fields = fields
18
+ @weight = weight || RediSearcher::DEFAULT_WEIGHT
19
+ end
20
+
21
+ def add(**options)
22
+ index.client.call(ft_add(options))
23
+ end
24
+
25
+ def del(**options)
26
+ index.client.call(ft_del(options))
27
+ end
28
+
29
+ private
30
+
31
+ def ft_add(**options)
32
+ ['FT.ADD', index.name , doc_id, weight, *serialize_options(:add, options), 'FIELDS', *serialize_fields]
33
+ end
34
+
35
+ def ft_del(**options)
36
+ ['FT.DEL', index.name , doc_id, *serialize_options(:del, options)]
37
+ end
38
+
39
+ def serialize_fields
40
+ fields.map do |key, value|
41
+ [(key.to_s rescue key) || key, value]
42
+ end.compact
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,69 @@
1
+ module RediSearcher
2
+ class Index < Client::CommandBase
3
+ OPTIONS_FLAGS = {
4
+ create: [:nooffsets, :nofreqs, :nohl, :nofields],
5
+ drop: [:keepdocs],
6
+ search: [:nocontent, :verbatim, :nostopwords, :withscores, :withsortkeys],
7
+ }
8
+
9
+ OPTIONS_PARAMS = {
10
+ create: [:stopwords],
11
+ search: [:filter, :return, :infields, :inkeys, :slop, :scorer, :sortby, :limit, :payload],
12
+ }
13
+
14
+ attr_reader :client, :name, :schema
15
+
16
+ def initialize(client, name, schema)
17
+ @client = client
18
+ @name = name
19
+ @schema = RediSearcher::Schema.new(schema)
20
+ end
21
+
22
+ def generate_document(id, fields)
23
+ RediSearcher::Document.new(self, id, fields)
24
+ end
25
+
26
+ def create(**options)
27
+ client.call(ft_create(schema, options))
28
+ end
29
+
30
+ def info
31
+ Hash[*client.call(ft_info)]
32
+ rescue Redis::CommandError
33
+ nil
34
+ end
35
+
36
+ def search(query, **options)
37
+ client.call(ft_search(query, options))
38
+ end
39
+
40
+ def exists?
41
+ !info.nil?
42
+ end
43
+
44
+ def drop
45
+ !client.call(ft_drop()).nil?
46
+ rescue Redis::CommandError
47
+ nil
48
+ end
49
+
50
+ private
51
+
52
+ def ft_create(schema, **options)
53
+ ['FT.CREATE', name , *serialize_options(:create, options), 'SCHEMA', *schema.serialize]
54
+ end
55
+
56
+ def ft_drop(**options)
57
+ ['FT.DROP', name, *serialize_options(:drop, options)]
58
+ end
59
+
60
+ def ft_search(query, **options)
61
+ ['FT.SEARCH', name, query, *serialize_options(:search, options)]
62
+ end
63
+
64
+ def ft_info
65
+ ['FT.INFO', name]
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,22 @@
1
+ module RediSearcher
2
+ class Schema
3
+ attr_reader :fields
4
+
5
+ def initialize(**fields)
6
+ @fields = []
7
+ build_fields_params(fields).each do |value|
8
+ @fields << Field.new(*value)
9
+ end
10
+ end
11
+
12
+ def serialize
13
+ @fields.map(&:serialize)
14
+ end
15
+
16
+ private
17
+
18
+ def build_fields_params(**fields)
19
+ fields.map{ |key, value| [key, value.is_a?(Hash) ? value.to_a : value].flatten}
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ module RediSearcher
2
+ class Schema
3
+ class Field
4
+ OPTIONS_FLAGS = {
5
+ text: [:no_stem],
6
+ all: [:sortable, :no_index]
7
+ }
8
+
9
+ OPTIONS_PARAMS = {
10
+ text: [:phonetic, :weight],
11
+ tag: [:separator]
12
+ }
13
+
14
+ attr_reader :name, :type, :options
15
+
16
+ def initialize(name, type, **options)
17
+ @name = name
18
+ @type = type
19
+ @options = options
20
+ end
21
+
22
+ def serialize
23
+ [name.to_s, type.to_s.upcase, flags_for_type(type, options), params_for_type(type, options), flags_for_type(:all, options)].flatten
24
+ end
25
+
26
+ def flags_for_type(type, **options)
27
+ self.class::OPTIONS_FLAGS[type].to_a.map do |key|
28
+ key.to_s.upcase if options[key]
29
+ end.compact
30
+ end
31
+
32
+ def params_for_type(type, **options)
33
+ self.class::OPTIONS_PARAMS[type].to_a.map do |key|
34
+ [key.to_s.upcase, *options[key]] unless options[key].nil?
35
+ end.compact
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module RediSearcher
2
+ VERSION = '0.1.2'
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "redi_searcher/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redi_searcher"
7
+ s.version = RediSearcher::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Patricio Beckmann"]
10
+ s.email = ["pato.beckmann@gmail.com"]
11
+ s.homepage = "https://github.com/Ticketplus/redi_searcher"
12
+ s.summary = %q{RediSearch ruby client}
13
+ s.description = %q{''}
14
+ s.required_ruby_version = '>= 2.3'
15
+ s.license = 'MIT'
16
+
17
+ s.add_dependency "redis", ">= 3.0"
18
+
19
+ s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(spec/)}) }
20
+
21
+ s.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redi_searcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Patricio Beckmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: "''"
28
+ email:
29
+ - pato.beckmann@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - lib/redi_searcher.rb
36
+ - lib/redi_searcher/client.rb
37
+ - lib/redi_searcher/client/command_base.rb
38
+ - lib/redi_searcher/document.rb
39
+ - lib/redi_searcher/index.rb
40
+ - lib/redi_searcher/schema.rb
41
+ - lib/redi_searcher/schema/field.rb
42
+ - lib/redi_searcher/version.rb
43
+ - redi_searcher.gemspec
44
+ homepage: https://github.com/Ticketplus/redi_searcher
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '2.3'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.0.1
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: RediSearch ruby client
67
+ test_files: []