Skip to content

Commit d267e10

Browse files
authored
Merge pull request #781 from MITLibraries/gdt-135-geodistance
Adds geo_distance query to opensearch
2 parents dfc1529 + 726b2d7 commit d267e10

File tree

4 files changed

+75
-23
lines changed

4 files changed

+75
-23
lines changed

.codeclimate.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
plugins:
22
rubocop:
33
enabled: true
4-
channel: rubocop-1-23-0
4+
channel: rubocop-1-56-3
5+

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
AllCops:
2-
TargetRubyVersion: 2.7
2+
TargetRubyVersion: 3.1
33
NewCops: enable
44
Exclude:
55
- "db/**/*"

app/models/opensearch.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def search(from, params, client, highlight = false, index = nil)
66
@params = params
77
@highlight = highlight
88
index = default_index unless index.present?
9-
client.search(index: index,
9+
client.search(index:,
1010
body: build_query(from))
1111
end
1212

@@ -17,10 +17,10 @@ def default_index
1717
# Construct the json query to send to elasticsearch
1818
def build_query(from)
1919
query_hash = {
20-
from: from,
20+
from:,
2121
size: SIZE,
22-
query: query,
23-
aggregations: aggregations
22+
query:,
23+
aggregations:
2424
}
2525

2626
query_hash[:highlight] = highlight if @highlight
@@ -109,9 +109,30 @@ def matches
109109
match_single_field_nested(:identifiers, m)
110110
match_single_field_nested(:locations, m)
111111
match_single_field_nested(:subjects, m)
112+
113+
match_geodistance(m) if @params[:geodistance].present?
112114
m
113115
end
114116

117+
def match_geodistance(match_array)
118+
match_array << {
119+
bool: {
120+
must: {
121+
match_all: {}
122+
},
123+
filter: {
124+
geo_distance: {
125+
distance: @params[:geodistance][:distance],
126+
'locations.geoshape': {
127+
lat: @params[:geodistance][:latitude],
128+
lon: @params[:geodistance][:longitude]
129+
}
130+
}
131+
}
132+
}
133+
}
134+
end
135+
115136
# https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html
116137
def filters(params)
117138
f = []
@@ -177,7 +198,7 @@ def source_array(param)
177198
param.each do |source|
178199
sources << {
179200
term: {
180-
source: source
201+
source:
181202
}
182203
}
183204
end

test/models/opensearch_test.rb

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,66 @@ class OpensearchTest < ActiveSupport::TestCase
44
test 'matches citation' do
55
os = Opensearch.new
66
os.instance_variable_set(:@params, { citation: 'foo' })
7-
assert os.matches.select { |m| m[:citation] == 'foo' }
7+
8+
assert(os.matches.to_json.include?('{"match":{"citation":"foo"}}'))
89
end
910

1011
test 'matches title' do
1112
os = Opensearch.new
1213
os.instance_variable_set(:@params, { title: 'foo' })
13-
assert os.matches.select { |m| m[:title] == 'foo' }
14+
15+
assert(os.matches.to_json.include?('{"match":{"title":"foo"}}'))
1416
end
1517

1618
test 'matches contributors' do
1719
os = Opensearch.new
1820
os.instance_variable_set(:@params, { contributors: 'foo' })
19-
assert os.matches.select { |m| m['contributors.value'] == 'foo' }
21+
22+
assert(os.matches.to_json.include?('{"match":{"contributors.value":"foo"}}'))
2023
end
2124

2225
test 'matches funding_information' do
2326
os = Opensearch.new
2427
os.instance_variable_set(:@params, { funding_information: 'foo' })
25-
assert os.matches.select { |m| m['funding_information.funder_name'] == 'foo' }
28+
29+
assert(os.matches.to_json.include?('{"match":{"funding_information.funder_name":"foo"}}'))
2630
end
2731

2832
test 'matches identifiers' do
2933
os = Opensearch.new
3034
os.instance_variable_set(:@params, { identifiers: 'foo' })
31-
assert os.matches.select { |m| m['identifiers.value'] == 'foo' }
35+
36+
assert(os.matches.to_json.include?('{"match":{"identifiers.value":"foo"}}'))
3237
end
3338

3439
test 'matches locations' do
3540
os = Opensearch.new
3641
os.instance_variable_set(:@params, { locations: 'foo' })
37-
assert os.matches.select { |m| m['locations.value'] == 'foo' }
42+
43+
assert(os.matches.to_json.include?('{"match":{"locations.value":"foo"}}'))
3844
end
3945

4046
test 'matches subjects' do
4147
os = Opensearch.new
4248
os.instance_variable_set(:@params, { subjects: 'foo' })
43-
assert os.matches.select { |m| m['subjects.value'] == 'foo' }
49+
50+
assert(os.matches.to_json.include?('{"match":{"subjects.value":"foo"}}'))
4451
end
4552

4653
test 'matches everything' do
4754
os = Opensearch.new
4855
os.instance_variable_set(:@params, { q: 'this', citation: 'here', title: 'is', contributors: 'a',
4956
funding_information: 'real', identifiers: 'search', locations: 'rest',
5057
subjects: 'assured,' })
51-
matches = os.matches
52-
assert matches.select { |m| m[:q] == 'this' }
53-
assert matches.select { |m| m[:citation] == 'here' }
54-
assert matches.select { |m| m[:title] == 'is' }
55-
assert matches.select { |m| m['contributors.value'] == 'a' }
56-
assert matches.select { |m| m['funding_information.funder_name'] == 'real' }
57-
assert matches.select { |m| m['identifiers.value'] == 'search' }
58-
assert matches.select { |m| m['locations.value'] == 'rest' }
59-
assert matches.select { |m| m['subjects.value'] == 'assured' }
58+
59+
assert(os.matches.to_json.include?('{"multi_match":{"query":"this","fields":'))
60+
assert(os.matches.to_json.include?('{"match":{"citation":"here"}}'))
61+
assert(os.matches.to_json.include?('{"match":{"title":"is"}}'))
62+
assert(os.matches.to_json.include?('{"match":{"contributors.value":"a"}}'))
63+
assert(os.matches.to_json.include?('{"match":{"funding_information.funder_name":"real"}}'))
64+
assert(os.matches.to_json.include?('{"match":{"identifiers.value":"search"}}'))
65+
assert(os.matches.to_json.include?('{"match":{"locations.value":"rest"}}'))
66+
assert(os.matches.to_json.include?('{"match":{"subjects.value":"assured,"}}'))
6067
end
6168

6269
test 'can override index' do
@@ -266,4 +273,27 @@ class OpensearchTest < ActiveSupport::TestCase
266273

267274
refute(os.build_query(0).include?('highlight'))
268275
end
276+
277+
test 'can search by geopoint' do
278+
os = Opensearch.new
279+
os.instance_variable_set(:@params,
280+
{ geodistance: { latitude: '42.361145', longitude: '-71.057083', distance: '50mi' } })
281+
282+
assert(
283+
os.query.to_json.include?('{"distance":"50mi","locations.geoshape":{"lat":"42.361145","lon":"-71.057083"}}')
284+
)
285+
end
286+
287+
test 'can search for combination of geopoint and keyword' do
288+
os = Opensearch.new
289+
os.instance_variable_set(:@params,
290+
{ geodistance: { latitude: '42.361145', longitude: '-71.057083', distance: '50mi' },
291+
q: 'rail stations' })
292+
293+
assert(os.matches.to_json.include?('{"multi_match":{"query":"rail stations","fields":'))
294+
295+
assert(
296+
os.query.to_json.include?('{"distance":"50mi","locations.geoshape":{"lat":"42.361145","lon":"-71.057083"}}')
297+
)
298+
end
269299
end

0 commit comments

Comments
 (0)