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 +7 -0
- data/.gitignore +11 -0
- data/lib/redi_searcher.rb +20 -0
- data/lib/redi_searcher/client.rb +37 -0
- data/lib/redi_searcher/client/command_base.rb +27 -0
- data/lib/redi_searcher/document.rb +46 -0
- data/lib/redi_searcher/index.rb +69 -0
- data/lib/redi_searcher/schema.rb +22 -0
- data/lib/redi_searcher/schema/field.rb +40 -0
- data/lib/redi_searcher/version.rb +3 -0
- data/redi_searcher.gemspec +22 -0
- metadata +67 -0
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,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,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: []
|