solrb 0.1.0
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/.circleci/config.yml +69 -0
- data/.circleci/run-with-local-config.sh +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +30 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +83 -0
- data/LICENSE.txt +21 -0
- data/README.md +259 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/solr/commit/request.rb +15 -0
- data/lib/solr/configuration.rb +66 -0
- data/lib/solr/connection.rb +33 -0
- data/lib/solr/core_configuration/core_config.rb +44 -0
- data/lib/solr/core_configuration/core_config_builder.rb +51 -0
- data/lib/solr/core_configuration/dynamic_field.rb +17 -0
- data/lib/solr/core_configuration/field.rb +20 -0
- data/lib/solr/delete/request.rb +34 -0
- data/lib/solr/document.rb +26 -0
- data/lib/solr/document_collection.rb +55 -0
- data/lib/solr/errors/ambiguous_core_error.rb +9 -0
- data/lib/solr/errors/solr_query_error.rb +4 -0
- data/lib/solr/errors/solr_url_not_defined_error.rb +16 -0
- data/lib/solr/grouped_document_collection.rb +38 -0
- data/lib/solr/indexing/document.rb +25 -0
- data/lib/solr/indexing/request.rb +22 -0
- data/lib/solr/query/request/boost_magnitude.rb +9 -0
- data/lib/solr/query/request/boosting/dictionary_boost_function.rb +36 -0
- data/lib/solr/query/request/boosting/exists_boost_function.rb +27 -0
- data/lib/solr/query/request/boosting/field_value_less_than_boost_function.rb +25 -0
- data/lib/solr/query/request/boosting/field_value_match_boost_function.rb +24 -0
- data/lib/solr/query/request/boosting/geodist_function.rb +37 -0
- data/lib/solr/query/request/boosting/ln_function_boost.rb +28 -0
- data/lib/solr/query/request/boosting/numeric_field_value_match_boost_function.rb +13 -0
- data/lib/solr/query/request/boosting/phrase_proximity_boost.rb +27 -0
- data/lib/solr/query/request/boosting/ranking_field_boost_function.rb +20 -0
- data/lib/solr/query/request/boosting/recent_field_value_boost_function.rb +26 -0
- data/lib/solr/query/request/boosting/scale_function_boost.rb +28 -0
- data/lib/solr/query/request/boosting/textual_field_value_match_boost_function.rb +13 -0
- data/lib/solr/query/request/boosting.rb +46 -0
- data/lib/solr/query/request/edismax_adapter.rb +163 -0
- data/lib/solr/query/request/facet.rb +68 -0
- data/lib/solr/query/request/field_with_boost.rb +18 -0
- data/lib/solr/query/request/filter.rb +73 -0
- data/lib/solr/query/request/geo_filter.rb +26 -0
- data/lib/solr/query/request/grouping.rb +37 -0
- data/lib/solr/query/request/or_filter.rb +16 -0
- data/lib/solr/query/request/runner.rb +46 -0
- data/lib/solr/query/request/sorting/field.rb +16 -0
- data/lib/solr/query/request/sorting.rb +34 -0
- data/lib/solr/query/request/spellcheck.rb +74 -0
- data/lib/solr/query/request.rb +49 -0
- data/lib/solr/query/response/facet_value.rb +16 -0
- data/lib/solr/query/response/field_facets.rb +25 -0
- data/lib/solr/query/response/parser.rb +154 -0
- data/lib/solr/query/response/spellcheck.rb +42 -0
- data/lib/solr/query/response.rb +48 -0
- data/lib/solr/response/header.rb +25 -0
- data/lib/solr/response/http_status.rb +27 -0
- data/lib/solr/response/parser.rb +47 -0
- data/lib/solr/response/solr_error.rb +31 -0
- data/lib/solr/response.rb +52 -0
- data/lib/solr/support/connection_helper.rb +12 -0
- data/lib/solr/support/hash_extensions.rb +29 -0
- data/lib/solr/support/schema_helper.rb +11 -0
- data/lib/solr/support/string_extensions.rb +12 -0
- data/lib/solr/support/url_helper.rb +12 -0
- data/lib/solr/support.rb +5 -0
- data/lib/solr/testing.rb +19 -0
- data/lib/solr/version.rb +3 -0
- data/lib/solr.rb +65 -0
- data/solrb.gemspec +36 -0
- metadata +261 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e90b9041817aa81077a2d05c9be0105682dedac1bb681d7cdd0802e2dd82e829
|
4
|
+
data.tar.gz: ac2d9553669c73c72e57bbba5636cd325c31141c859463dbf88908e0e0f070c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 154b62204ff427c13b7eedf8cf0dbe18d18d73093402f6a74a0f292e4f226929bce30a874d7586e50beff08b1b74c792f2702f9f277351e825a80d9367c1af18
|
7
|
+
data.tar.gz: 1bfd971cb1973195288dec35d37911fceb98fc4ef4a76123a9e09261b97d7e8c9ead7ec851074ce3df9698421423298ea00aed3d38bee0b3eb78e6ae575b34e9
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
# primary image where all specs are run
|
10
|
+
- image: circleci/ruby:2.5.1-node-browsers
|
11
|
+
environment:
|
12
|
+
SOLR_URL: http://localhost:8983/solr/test-core
|
13
|
+
# service images that primary image will use
|
14
|
+
- image: solr:7.4.0
|
15
|
+
|
16
|
+
working_directory: ~/repo
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- checkout
|
20
|
+
|
21
|
+
# Download and cache dependencies
|
22
|
+
- restore_cache:
|
23
|
+
keys:
|
24
|
+
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
25
|
+
# fallback to using the latest cache if no exact match is found
|
26
|
+
- v1-dependencies-
|
27
|
+
|
28
|
+
- run:
|
29
|
+
name: install dependencies
|
30
|
+
command: |
|
31
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
32
|
+
|
33
|
+
- save_cache:
|
34
|
+
paths:
|
35
|
+
- ./vendor/bundle
|
36
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
37
|
+
|
38
|
+
- run:
|
39
|
+
name: Wait for Solr
|
40
|
+
command: dockerize -wait tcp://localhost:8983 -timeout 1m
|
41
|
+
|
42
|
+
- run:
|
43
|
+
name: Create a test core
|
44
|
+
command: curl 'http://localhost:8983/solr/admin/cores?action=CREATE&name=test-core&configSet=_default'
|
45
|
+
|
46
|
+
- run:
|
47
|
+
name: Disable field type guessing
|
48
|
+
command: |
|
49
|
+
curl http://localhost:8983/solr/test-core/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'
|
50
|
+
|
51
|
+
|
52
|
+
- run:
|
53
|
+
name: run tests
|
54
|
+
command: |
|
55
|
+
mkdir /tmp/test-results
|
56
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
57
|
+
|
58
|
+
bundle exec rspec --format progress \
|
59
|
+
--format RspecJunitFormatter \
|
60
|
+
--out /tmp/test-results/rspec.xml \
|
61
|
+
--format progress \
|
62
|
+
$TEST_FILES
|
63
|
+
|
64
|
+
# collect reports
|
65
|
+
- store_test_results:
|
66
|
+
path: /tmp/test-results
|
67
|
+
- store_artifacts:
|
68
|
+
path: /tmp/test-results
|
69
|
+
destination: test-results
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- db/schema.rb
|
4
|
+
- node_modules/**/*
|
5
|
+
- bin/*
|
6
|
+
TargetRubyVersion: '2.5'
|
7
|
+
Metrics/LineLength:
|
8
|
+
Max: 120
|
9
|
+
Documentation:
|
10
|
+
Enabled: false
|
11
|
+
FrozenStringLiteralComment:
|
12
|
+
Enabled: false
|
13
|
+
Metrics/MethodLength:
|
14
|
+
Max: 20
|
15
|
+
Metrics/AbcSize:
|
16
|
+
Max: 20
|
17
|
+
# Removing Blocks Cop for RSpec
|
18
|
+
Style/BlockDelimiters:
|
19
|
+
Exclude:
|
20
|
+
- 'spec/**/*'
|
21
|
+
# Removing Indentation Cop for RSpec
|
22
|
+
Layout/MultilineMethodCallIndentation:
|
23
|
+
Exclude:
|
24
|
+
- 'spec/**/*'
|
25
|
+
Metrics/BlockLength:
|
26
|
+
Exclude:
|
27
|
+
- 'Rakefile'
|
28
|
+
- '**/*.rake'
|
29
|
+
- 'spec/**/*'
|
30
|
+
- 'config/environments/**/*'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.1
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
solrb (0.1.0)
|
5
|
+
addressable
|
6
|
+
faraday
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
addressable (2.5.2)
|
12
|
+
public_suffix (>= 2.0.2, < 4.0)
|
13
|
+
ast (2.4.0)
|
14
|
+
byebug (10.0.2)
|
15
|
+
coderay (1.1.2)
|
16
|
+
diff-lcs (1.3)
|
17
|
+
docile (1.3.1)
|
18
|
+
faraday (0.15.2)
|
19
|
+
multipart-post (>= 1.2, < 3)
|
20
|
+
jaro_winkler (1.5.1)
|
21
|
+
json (2.1.0)
|
22
|
+
method_source (0.9.0)
|
23
|
+
multipart-post (2.0.0)
|
24
|
+
parallel (1.12.1)
|
25
|
+
parser (2.5.1.2)
|
26
|
+
ast (~> 2.4.0)
|
27
|
+
powerpack (0.1.2)
|
28
|
+
pry (0.11.3)
|
29
|
+
coderay (~> 1.1.0)
|
30
|
+
method_source (~> 0.9.0)
|
31
|
+
pry-byebug (3.6.0)
|
32
|
+
byebug (~> 10.0)
|
33
|
+
pry (~> 0.10)
|
34
|
+
public_suffix (3.0.2)
|
35
|
+
rainbow (3.0.0)
|
36
|
+
rake (10.5.0)
|
37
|
+
rspec (3.8.0)
|
38
|
+
rspec-core (~> 3.8.0)
|
39
|
+
rspec-expectations (~> 3.8.0)
|
40
|
+
rspec-mocks (~> 3.8.0)
|
41
|
+
rspec-core (3.8.0)
|
42
|
+
rspec-support (~> 3.8.0)
|
43
|
+
rspec-expectations (3.8.0)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.8.0)
|
46
|
+
rspec-mocks (3.8.0)
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
+
rspec-support (~> 3.8.0)
|
49
|
+
rspec-support (3.8.0)
|
50
|
+
rspec_junit_formatter (0.4.1)
|
51
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
52
|
+
rubocop (0.58.2)
|
53
|
+
jaro_winkler (~> 1.5.1)
|
54
|
+
parallel (~> 1.10)
|
55
|
+
parser (>= 2.5, != 2.5.1.1)
|
56
|
+
powerpack (~> 0.1)
|
57
|
+
rainbow (>= 2.2.2, < 4.0)
|
58
|
+
ruby-progressbar (~> 1.7)
|
59
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
60
|
+
ruby-progressbar (1.10.0)
|
61
|
+
simplecov (0.16.1)
|
62
|
+
docile (~> 1.1)
|
63
|
+
json (>= 1.8, < 3)
|
64
|
+
simplecov-html (~> 0.10.0)
|
65
|
+
simplecov-html (0.10.2)
|
66
|
+
unicode-display_width (1.4.0)
|
67
|
+
|
68
|
+
PLATFORMS
|
69
|
+
ruby
|
70
|
+
|
71
|
+
DEPENDENCIES
|
72
|
+
bundler (~> 1.16)
|
73
|
+
pry
|
74
|
+
pry-byebug
|
75
|
+
rake (~> 10.0)
|
76
|
+
rspec (~> 3.0)
|
77
|
+
rspec_junit_formatter
|
78
|
+
rubocop
|
79
|
+
simplecov
|
80
|
+
solrb!
|
81
|
+
|
82
|
+
BUNDLED WITH
|
83
|
+
1.16.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Adriano Luz, Valentin Vasilyev
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
[](https://circleci.com/gh/machinio/solrb/tree/master)
|
2
|
+
[](https://codeclimate.com/github/machinio/solrb/maintainability)
|
3
|
+
|
4
|
+
# Solrb [WIP]
|
5
|
+
|
6
|
+
Object-Oriented approach to Solr in Ruby.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'solrb', require: 'solr'
|
14
|
+
```
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
|
18
|
+
The simplest way to use Solrb is `SORL_URL` environment variable (that has a core name in it):
|
19
|
+
|
20
|
+
```bash
|
21
|
+
ENV['SOLR_URL'] = 'http://localhost:8983/solr/demo'
|
22
|
+
```
|
23
|
+
|
24
|
+
or through `Solr.configure` to specify the solr URL:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# Single core configuration
|
28
|
+
Solr.configure do |config|
|
29
|
+
config.url = 'http://localhost:8983/solr/demo'
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Use `Solr.configure` for an additional configuration:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# Single core configuration
|
37
|
+
Solr.configure do |config|
|
38
|
+
config.url = 'http://localhost:8983/solr/demo'
|
39
|
+
|
40
|
+
# This gem uses faraday to make requests to Solr. You can specify additional faraday
|
41
|
+
# options here.
|
42
|
+
config.faraday_options = {}
|
43
|
+
|
44
|
+
# Core's URL is 'http://localhost:8983/solr/demo'
|
45
|
+
# Adding fields to work with
|
46
|
+
config.define_core do |f|
|
47
|
+
f.field :title, dynamic_field: :text
|
48
|
+
f.dynamic_field :text, solr_name: '*_text'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# Multiple core configuration
|
55
|
+
Solr.configure do |config|
|
56
|
+
config.url = 'http://localhost:8983/solr'
|
57
|
+
|
58
|
+
# Define a core with fields that will be used with Solr.
|
59
|
+
# Core URL is 'http://localhost:8983/solr/listings'
|
60
|
+
config.define_core(name: :listings) do |f|
|
61
|
+
# When a dynamic_field is present, the field name will be mapped to match the dynamic field.
|
62
|
+
# Here, "title" will be mapped to "title_text"
|
63
|
+
# You must define a dynamic field to be able to use the dynamic_field option
|
64
|
+
f.field :title, dynamic_field: :text
|
65
|
+
|
66
|
+
# When solr_name is present, the field name will be mapped to the solr_name at runtime
|
67
|
+
f.field :tags, solr_name: :tags_array
|
68
|
+
|
69
|
+
# define a dynamic field
|
70
|
+
f.dynamic_field :text, solr_name: '*_text'
|
71
|
+
end
|
72
|
+
|
73
|
+
# Pass `default: true` to use one core as a default.
|
74
|
+
# Core's URL is 'http://localhost:8983/solr/cars'
|
75
|
+
config.define_core(name: :cars, default: true) do |f|
|
76
|
+
f.field :manufacturer, solr_name: :manuf_s
|
77
|
+
f.field :model, solr_name: :model_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
It's important to note that those fields that are not configured, will be passed as-is to solr.
|
83
|
+
*So you only need to specify fields in configuration if you want Solrb to modify them at runtime*.
|
84
|
+
|
85
|
+
|
86
|
+
Warning: Solrb doesn't support fields with the same name. If you have two fields with the same name mapping
|
87
|
+
to a single solr field, you'll have to rename one of the fields.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
...
|
91
|
+
config.define_core do |f|
|
92
|
+
...
|
93
|
+
# Not allowed: Two fields with same name 'title'
|
94
|
+
f.field :title, solr_name: :article_title
|
95
|
+
f.field :title, solr_name: :page_title
|
96
|
+
end
|
97
|
+
...
|
98
|
+
```
|
99
|
+
|
100
|
+
## Usage
|
101
|
+
|
102
|
+
### Indexing
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
# creates a single document and commits it to index
|
106
|
+
doc = Solr::Indexing::Document.new
|
107
|
+
doc.add_field(:id, 1)
|
108
|
+
doc.add_field(:name, 'Solrb!!!')
|
109
|
+
|
110
|
+
request = Solr::Indexing::Request.new(documents: [doc])
|
111
|
+
request.run(commit: true)
|
112
|
+
```
|
113
|
+
|
114
|
+
You can also create indexing document directly from attributes:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
doc = Solr::Indexing::Document.new(id: 5, name: 'John')
|
118
|
+
```
|
119
|
+
|
120
|
+
### Querying
|
121
|
+
|
122
|
+
#### Simple Query
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
field = Solr::Query::Request::FieldWithBoost.new(field: :name)
|
126
|
+
|
127
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: [field])
|
128
|
+
request.run(page: 1, page_size: 10)
|
129
|
+
```
|
130
|
+
|
131
|
+
#### Query with field boost
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
fields = [
|
135
|
+
# Use boost_magnitude argument to apply boost to a specific field that you query
|
136
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name, boost_magnitude: 16),
|
137
|
+
Solr::Query::Request::FieldWithBoost.new(field: :title)
|
138
|
+
]
|
139
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
140
|
+
request.run(page: 1, page_size: 10)
|
141
|
+
```
|
142
|
+
|
143
|
+
#### Query with filters
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
fields = [
|
147
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
148
|
+
Solr::Query::Request::FieldWithBoost.new(field: :title)
|
149
|
+
]
|
150
|
+
filters = [Solr::Query::Request::Filter.new(type: :equal, field: :title, value: 'A title')]
|
151
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields, filters: filters)
|
152
|
+
request.run(page: 1, page_size: 10)
|
153
|
+
```
|
154
|
+
|
155
|
+
|
156
|
+
#### Query with sorting
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
fields = [
|
160
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
161
|
+
Solr::Query::Request::FieldWithBoost.new(field: :title)
|
162
|
+
]
|
163
|
+
sort_fields = [Solr::Query::Request::Sorting::Field.new(name: :name, direction: :asc)]
|
164
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
165
|
+
request.sorting = Solr::Query::Request::Sorting.new(fields: sort_fields)
|
166
|
+
request.run(page: 1, page_size: 10)
|
167
|
+
```
|
168
|
+
|
169
|
+
#### Query with grouping
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
fields = [
|
173
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
174
|
+
Solr::Query::Request::FieldWithBoost.new(field: :category)
|
175
|
+
]
|
176
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
177
|
+
request.grouping = Solr::Query::Request::Grouping.new(field: :category, limit: 10)
|
178
|
+
request.run(page: 1, page_size: 10)
|
179
|
+
```
|
180
|
+
|
181
|
+
#### Query with facets
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
fields = [
|
185
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
186
|
+
Solr::Query::Request::FieldWithBoost.new(field: :category)
|
187
|
+
]
|
188
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
189
|
+
request.facets = [Solr::Query::Request::Facet.new(type: :terms, field: :category, options: { limit: 10 })]
|
190
|
+
request.run(page: 1, page_size: 10)
|
191
|
+
```
|
192
|
+
|
193
|
+
#### Query with boosting functions
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
fields = [
|
197
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
198
|
+
Solr::Query::Request::FieldWithBoost.new(field: :category)
|
199
|
+
]
|
200
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
201
|
+
request.boosting = Solr::Query::Request::Boosting.new(
|
202
|
+
multiplicative_boost_functions: [Solr::Query::Request::Boosting::RankingFieldBoostFunction.new(field: :name)],
|
203
|
+
phrase_boosts: [Solr::Query::Request::Boosting::PhraseProximityBoost.new(field: :category, boost_magnitude: 4)]
|
204
|
+
)
|
205
|
+
request.run(page: 1, page_size: 10)
|
206
|
+
```
|
207
|
+
|
208
|
+
#### Field list
|
209
|
+
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
fields = [
|
213
|
+
Solr::Query::Request::FieldWithBoost.new(field: :name),
|
214
|
+
Solr::Query::Request::FieldWithBoost.new(field: :category)
|
215
|
+
]
|
216
|
+
request = Solr::Query::Request.new(search_term: 'term', fields: fields)
|
217
|
+
# Solr::Query::Request will return only :id field by default.
|
218
|
+
# Specify additional return fields (fl param) by setting the request response_fields
|
219
|
+
request.response_fields = [:name, :category]
|
220
|
+
request.run(page: 1, page_size: 10)
|
221
|
+
```
|
222
|
+
|
223
|
+
### Deleting documents
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
Solr.delete_by_id(3242343)
|
227
|
+
Solr.delete_by_id(3242343, commit: true)
|
228
|
+
Solr.delete_by_query('*:*')
|
229
|
+
Solr.delete_by_query('*:*', commit: true)
|
230
|
+
```
|
231
|
+
|
232
|
+
### Using multi-core configuration
|
233
|
+
|
234
|
+
For multi-core configuration use `Solr.with_core` block:
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
Solr.with_core(:models) do
|
238
|
+
Solr.delete_by_id(3242343)
|
239
|
+
Solr::Query::Request.new(search_term: 'term', fields: fields)
|
240
|
+
Solr::Indexing::Request.new(documents: [doc])
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
## Running specs
|
245
|
+
|
246
|
+
This project is setup to use CI to run all specs agains a real solr.
|
247
|
+
|
248
|
+
If you want to run it locally, you can either use [CircleCI CLI](https://circleci.com/docs/2.0/local-cli/)
|
249
|
+
or do a completely manual setup (for up-to-date steps see circleci config)
|
250
|
+
|
251
|
+
```sh
|
252
|
+
docker pull solr:7.4.0
|
253
|
+
docker run -it --name test-solr -p 8983:8983/tcp -t solr:7.4.0
|
254
|
+
# create a core
|
255
|
+
curl 'http://localhost:8983/solr/admin/cores?action=CREATE&name=test-core&configSet=_default'
|
256
|
+
# disable field guessing
|
257
|
+
curl http://localhost:8983/solr/test-core/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'
|
258
|
+
SOLR_URL=http://localhost:8983/solr/test-core rspec
|
259
|
+
```
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "solr"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Solr
|
2
|
+
module Commit
|
3
|
+
class Request
|
4
|
+
include Solr::Support::ConnectionHelper
|
5
|
+
PATH = '/update'.freeze
|
6
|
+
|
7
|
+
def run
|
8
|
+
# the way to do commit message in SOLR is to send an empty
|
9
|
+
# request with ?commit=true in the URL.
|
10
|
+
raw_response = connection(PATH, commit: true).post
|
11
|
+
Solr::Response.from_raw_response(raw_response)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'solr/core_configuration/dynamic_field'
|
2
|
+
require 'solr/core_configuration/field'
|
3
|
+
require 'solr/core_configuration/core_config'
|
4
|
+
require 'solr/core_configuration/core_config_builder'
|
5
|
+
require 'solr/errors/solr_url_not_defined_error'
|
6
|
+
require 'solr/errors/ambiguous_core_error'
|
7
|
+
|
8
|
+
module Solr
|
9
|
+
class Configuration
|
10
|
+
attr_accessor :faraday_options, :cores, :test_connection
|
11
|
+
attr_reader :url
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@faraday_options = {
|
15
|
+
request: { timeout: 2, open_timeout: 8 },
|
16
|
+
headers: { user_agent: "Solrb v#{Solr::VERSION}" }
|
17
|
+
}
|
18
|
+
@cores = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def url=(value)
|
22
|
+
if value.nil?
|
23
|
+
raise ArgumentError, "Solr's URL can't be nil"
|
24
|
+
else
|
25
|
+
@url = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def core_config_by_name(core)
|
30
|
+
cores[core.to_sym] || build_env_url_core_config(name: core)
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_core_config
|
34
|
+
defined_default_core_config = cores.values.detect(&:default?)
|
35
|
+
return defined_default_core_config if defined_default_core_config
|
36
|
+
raise Errors::AmbiguousCoreError if cores.count > 1
|
37
|
+
cores.values.first || build_env_url_core_config
|
38
|
+
end
|
39
|
+
|
40
|
+
def define_core(name: nil, default: false)
|
41
|
+
validate_default_core_config!(default: default)
|
42
|
+
builder = Solr::CoreConfiguration::CoreConfigBuilder.new(
|
43
|
+
name: name,
|
44
|
+
default: default
|
45
|
+
)
|
46
|
+
yield builder
|
47
|
+
core = builder.build
|
48
|
+
if cores.has_key?(core.name)
|
49
|
+
raise "A core with name '#{core.name}' has been already defined"
|
50
|
+
else
|
51
|
+
cores[core.name] = core
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_env_url_core_config(name: nil)
|
56
|
+
Solr::CoreConfiguration::EnvUrlCoreConfig.new(name: name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_default_core_config!(default:)
|
60
|
+
return unless default
|
61
|
+
if cores.any? { |name, core_config| core_config.default? }
|
62
|
+
raise ArgumentError, 'Only one default core can be specified'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Solr
|
2
|
+
# low-level connection that can do network requests to Solr
|
3
|
+
class Connection
|
4
|
+
INSTRUMENT_KEY = 'solrb.request'.freeze
|
5
|
+
|
6
|
+
def initialize(url, faraday_options: Solr.configuration.faraday_options)
|
7
|
+
# Allow mock the connection for testing
|
8
|
+
@raw_connection = Solr.configuration.test_connection || Faraday.new(url, faraday_options)
|
9
|
+
freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def get
|
13
|
+
Solr.instrument(name: INSTRUMENT_KEY) { @raw_connection.get }
|
14
|
+
end
|
15
|
+
|
16
|
+
def post(data = {})
|
17
|
+
Solr.instrument(name: INSTRUMENT_KEY) do
|
18
|
+
@raw_connection.post do |req|
|
19
|
+
req.body = data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def post_as_json(data)
|
25
|
+
Solr.instrument(name: INSTRUMENT_KEY, data: data) do
|
26
|
+
@raw_connection.post do |req|
|
27
|
+
req.headers['Content-Type'] = 'application/json'.freeze
|
28
|
+
req.body = JSON.generate(data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|