Commit 7a1f2508a4ad72b9d6dc81376c9c21ade5e9719c
1 parent
515938a6
Exists in
master
and in
21 other branches
Added support for {lat: lat, lon: lon} as preferred format for locations - #579
Showing
6 changed files
with
69 additions
and
13 deletions
Show diff stats
CHANGELOG.md
README.md
... | ... | @@ -779,7 +779,7 @@ class City < ActiveRecord::Base |
779 | 779 | searchkick locations: ["location"] |
780 | 780 | |
781 | 781 | def search_data |
782 | - attributes.merge location: [latitude, longitude] | |
782 | + attributes.merge location: {lat: latitude, lon: longitude} | |
783 | 783 | end |
784 | 784 | end |
785 | 785 | ``` |
... | ... | @@ -787,13 +787,13 @@ end |
787 | 787 | Reindex and search with: |
788 | 788 | |
789 | 789 | ```ruby |
790 | -City.search "san", where: {location: {near: [37, -114], within: "100mi"}} # or 160km | |
790 | +City.search "san", where: {location: {near: {lat: 37, lon: -114}, within: "100mi"}} # or 160km | |
791 | 791 | ``` |
792 | 792 | |
793 | 793 | Bounded by a box |
794 | 794 | |
795 | 795 | ```ruby |
796 | -City.search "san", where: {location: {top_left: [38, -123], bottom_right: [37, -122]}} | |
796 | +City.search "san", where: {location: {top_left: {lat: 38, lon: -123}, bottom_right: {lat: 37, lon: -122}}} | |
797 | 797 | ``` |
798 | 798 | |
799 | 799 | ### Boost By Distance |
... | ... | @@ -801,13 +801,13 @@ City.search "san", where: {location: {top_left: [38, -123], bottom_right: [37, - |
801 | 801 | Boost results by distance - closer results are boosted more |
802 | 802 | |
803 | 803 | ```ruby |
804 | -City.search "san", boost_by_distance: {field: :location, origin: [37, -122]} | |
804 | +City.search "san", boost_by_distance: {field: :location, origin: {lat: 37, lon: -122}} | |
805 | 805 | ``` |
806 | 806 | |
807 | 807 | Also supports [additional options](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_decay_functions) |
808 | 808 | |
809 | 809 | ```ruby |
810 | -City.search "san", boost_by_distance: {field: :location, origin: [37, -122], function: :linear, scale: "30mi", decay: 0.5} | |
810 | +City.search "san", boost_by_distance: {field: :location, origin: {lat: 37, lon: -122}, function: :linear, scale: "30mi", decay: 0.5} | |
811 | 811 | ``` |
812 | 812 | |
813 | 813 | ### Routing | ... | ... |
lib/searchkick/index.rb
... | ... | @@ -568,10 +568,11 @@ module Searchkick |
568 | 568 | # locations |
569 | 569 | (options[:locations] || []).map(&:to_s).each do |field| |
570 | 570 | if source[field] |
571 | - if source[field].first.is_a?(Array) # array of arrays | |
572 | - source[field] = source[field].map { |a| a.map(&:to_f).reverse } | |
571 | + if !source[field].is_a?(Hash) && (source[field].first.is_a?(Array) || source[field].first.is_a?(Hash)) | |
572 | + # multiple locations | |
573 | + source[field] = source[field].map { |a| location_value(a) } | |
573 | 574 | else |
574 | - source[field] = source[field].map(&:to_f).reverse | |
575 | + source[field] = location_value(source[field]) | |
575 | 576 | end |
576 | 577 | end |
577 | 578 | end |
... | ... | @@ -581,6 +582,16 @@ module Searchkick |
581 | 582 | source.as_json |
582 | 583 | end |
583 | 584 | |
585 | + def location_value(value) | |
586 | + if value.is_a?(Array) | |
587 | + value.map(&:to_f).reverse | |
588 | + elsif value.is_a?(Hash) | |
589 | + {lat: value[:lat].to_f, lon: value[:lon].to_f} | |
590 | + else | |
591 | + value | |
592 | + end | |
593 | + end | |
594 | + | |
584 | 595 | # change all BigDecimal values to floats due to |
585 | 596 | # https://github.com/rails/rails/issues/6033 |
586 | 597 | # possible loss of precision :/ | ... | ... |
lib/searchkick/query.rb
... | ... | @@ -599,7 +599,7 @@ module Searchkick |
599 | 599 | when :near |
600 | 600 | filters << { |
601 | 601 | geo_distance: { |
602 | - field => op_value.map(&:to_f).reverse, | |
602 | + field => location_value(op_value), | |
603 | 603 | distance: value[:within] || "50mi" |
604 | 604 | } |
605 | 605 | } |
... | ... | @@ -607,8 +607,8 @@ module Searchkick |
607 | 607 | filters << { |
608 | 608 | geo_bounding_box: { |
609 | 609 | field => { |
610 | - top_left: op_value.map(&:to_f).reverse, | |
611 | - bottom_right: value[:bottom_right].map(&:to_f).reverse | |
610 | + top_left: location_value(op_value), | |
611 | + bottom_right: location_value(value[:bottom_right]) | |
612 | 612 | } |
613 | 613 | } |
614 | 614 | } |
... | ... | @@ -699,6 +699,14 @@ module Searchkick |
699 | 699 | end |
700 | 700 | end |
701 | 701 | |
702 | + def location_value(value) | |
703 | + if value.is_a?(Array) | |
704 | + value.map(&:to_f).reverse | |
705 | + else | |
706 | + value | |
707 | + end | |
708 | + end | |
709 | + | |
702 | 710 | def below12? |
703 | 711 | below_version?("1.2.0") |
704 | 712 | end | ... | ... |
test/test_helper.rb
... | ... | @@ -226,8 +226,8 @@ class Product |
226 | 226 | serializable_hash.except("id").merge( |
227 | 227 | conversions: conversions, |
228 | 228 | user_ids: user_ids, |
229 | - location: [latitude, longitude], | |
230 | - multiple_locations: [[latitude, longitude], [0, 0]], | |
229 | + location: {lat: latitude, lon: longitude}, | |
230 | + multiple_locations: [{lat: latitude, lon: longitude}, {lat: 0, lon: 0}], | |
231 | 231 | aisle: aisle |
232 | 232 | ) |
233 | 233 | end | ... | ... |
test/where_test.rb
... | ... | @@ -111,6 +111,14 @@ class WhereTest < Minitest::Test |
111 | 111 | assert_search "san", ["San Francisco"], where: {location: {near: [37.5, -122.5]}} |
112 | 112 | end |
113 | 113 | |
114 | + def test_near_hash | |
115 | + store [ | |
116 | + {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, | |
117 | + {name: "San Antonio", latitude: 29.4167, longitude: -98.5000} | |
118 | + ] | |
119 | + assert_search "san", ["San Francisco"], where: {location: {near: {lat: 37.5, lon: -122.5}}} | |
120 | + end | |
121 | + | |
114 | 122 | def test_near_within |
115 | 123 | store [ |
116 | 124 | {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, |
... | ... | @@ -120,6 +128,15 @@ class WhereTest < Minitest::Test |
120 | 128 | assert_search "san", ["San Francisco", "San Antonio"], where: {location: {near: [37, -122], within: "2000mi"}} |
121 | 129 | end |
122 | 130 | |
131 | + def test_near_within_hash | |
132 | + store [ | |
133 | + {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, | |
134 | + {name: "San Antonio", latitude: 29.4167, longitude: -98.5000}, | |
135 | + {name: "San Marino", latitude: 43.9333, longitude: 12.4667} | |
136 | + ] | |
137 | + assert_search "san", ["San Francisco", "San Antonio"], where: {location: {near: {lat: 37, lon: -122}, within: "2000mi"}} | |
138 | + end | |
139 | + | |
123 | 140 | def test_top_left_bottom_right |
124 | 141 | store [ |
125 | 142 | {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, |
... | ... | @@ -128,6 +145,14 @@ class WhereTest < Minitest::Test |
128 | 145 | assert_search "san", ["San Francisco"], where: {location: {top_left: [38, -123], bottom_right: [37, -122]}} |
129 | 146 | end |
130 | 147 | |
148 | + def test_top_left_bottom_right_hash | |
149 | + store [ | |
150 | + {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, | |
151 | + {name: "San Antonio", latitude: 29.4167, longitude: -98.5000} | |
152 | + ] | |
153 | + assert_search "san", ["San Francisco"], where: {location: {top_left: {lat: 38, lon: -123}, bottom_right: {lat: 37, lon: -122}}} | |
154 | + end | |
155 | + | |
131 | 156 | def test_multiple_locations |
132 | 157 | store [ |
133 | 158 | {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, |
... | ... | @@ -135,4 +160,12 @@ class WhereTest < Minitest::Test |
135 | 160 | ] |
136 | 161 | assert_search "san", ["San Francisco"], where: {multiple_locations: {near: [37.5, -122.5]}} |
137 | 162 | end |
163 | + | |
164 | + def test_multiple_locations_hash | |
165 | + store [ | |
166 | + {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, | |
167 | + {name: "San Antonio", latitude: 29.4167, longitude: -98.5000} | |
168 | + ] | |
169 | + assert_search "san", ["San Francisco"], where: {multiple_locations: {near: {lat: 37.5, lon: -122.5}}} | |
170 | + end | |
138 | 171 | end | ... | ... |