redi_searcher 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: []