Skip to content

Commit 92794b3

Browse files
committed
Adds opensearch geo_bounding_box query support
Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/GDT-167 How does this address that need: * Adds an optional geo_bounding_box search to our existing opensearch query builder
1 parent b4cfbb7 commit 92794b3

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

app/models/opensearch.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,34 @@ def matches
111111
match_single_field_nested(:subjects, m)
112112

113113
match_geodistance(m) if @params[:geodistance].present?
114+
match_geobox(m) if @params[:geobox].present?
114115
m
115116
end
116117

118+
# https://opensearch.org/docs/latest/query-dsl/geo-and-xy/geo-bounding-box/
119+
def match_geobox(match_array)
120+
match_array << {
121+
bool: {
122+
must: {
123+
match_all: {}
124+
},
125+
filter: {
126+
geo_bounding_box: {
127+
'locations.geoshape': {
128+
top: @params[:geobox][:max_latitude],
129+
bottom: @params[:geobox][:min_latitude],
130+
left: @params[:geobox][:min_longitude],
131+
right: @params[:geobox][:max_longitude]
132+
}
133+
}
134+
}
135+
}
136+
}
137+
end
138+
139+
# https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-geo-distance-query.html
140+
# Note: at the time of this implementation, opensearch does not have documentation on
141+
# this features hence the link to the prefork elasticsearch docs
117142
def match_geodistance(match_array)
118143
match_array << {
119144
bool: {

test/models/opensearch_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ class OpensearchTest < ActiveSupport::TestCase
279279
os.instance_variable_set(:@params,
280280
{ geodistance: { latitude: '42.361145', longitude: '-71.057083', distance: '50mi' } })
281281

282+
refute(os.matches.to_json.include?('{"multi_match":{"query":'))
283+
282284
assert(
283285
os.query.to_json.include?('{"distance":"50mi","locations.geoshape":{"lat":"42.361145","lon":"-71.057083"}}')
284286
)
@@ -296,4 +298,31 @@ class OpensearchTest < ActiveSupport::TestCase
296298
os.query.to_json.include?('{"distance":"50mi","locations.geoshape":{"lat":"42.361145","lon":"-71.057083"}}')
297299
)
298300
end
301+
302+
test 'can search by bounding box' do
303+
os = Opensearch.new
304+
os.instance_variable_set(:@params,
305+
{ geobox: { max_latitude: '42.886', min_latitude: '41.239',
306+
max_longitude: '-73.928', min_longitude: '-69.507' } })
307+
308+
refute(os.matches.to_json.include?('{"multi_match":{"query"'))
309+
310+
assert(
311+
os.query.to_json.include?('{"locations.geoshape":{"top":"42.886","bottom":"41.239","left":"-69.507","right":"-73.928"}}')
312+
)
313+
end
314+
315+
test 'can search by bounding box and keyword' do
316+
os = Opensearch.new
317+
os.instance_variable_set(:@params,
318+
{ geobox: { max_latitude: '42.886', min_latitude: '41.239',
319+
max_longitude: '-73.928', min_longitude: '-69.507' },
320+
q: 'rail stations' })
321+
322+
assert(os.matches.to_json.include?('{"multi_match":{"query":"rail stations","fields":'))
323+
324+
assert(
325+
os.query.to_json.include?('{"locations.geoshape":{"top":"42.886","bottom":"41.239","left":"-69.507","right":"-73.928"}}')
326+
)
327+
end
299328
end

0 commit comments

Comments
 (0)