lib/searchkick/index_options.rb in searchkick-5.3.1 vs lib/searchkick/index_options.rb in searchkick-5.4.0
- old
+ new
@@ -167,10 +167,25 @@
settings[:index] = {
max_ngram_diff: 49,
max_shingle_diff: 4
}
+ if options[:knn]
+ unless Searchkick.knn_support?
+ if Searchkick.opensearch?
+ raise Error, "knn requires OpenSearch 2.4+"
+ else
+ raise Error, "knn requires Elasticsearch 8.6+"
+ end
+ end
+
+ if Searchkick.opensearch? && options[:knn].any? { |_, v| !v[:distance].nil? }
+ # only enable if doing approximate search
+ settings[:index][:knn] = true
+ end
+ end
+
if options[:case_sensitive]
settings[:analysis][:analyzer].each do |_, analyzer|
analyzer[:filter].delete("lowercase")
end
end
@@ -402,9 +417,69 @@
end
options[:geo_shape] = options[:geo_shape].product([{}]).to_h if options[:geo_shape].is_a?(Array)
(options[:geo_shape] || {}).each do |field, shape_options|
mapping[field] = shape_options.merge(type: "geo_shape")
+ end
+
+ (options[:knn] || []).each do |field, knn_options|
+ distance = knn_options[:distance]
+
+ if Searchkick.opensearch?
+ if distance.nil?
+ # avoid server crash if method not specified
+ raise ArgumentError, "Must specify a distance for OpenSearch"
+ end
+
+ vector_options = {
+ type: "knn_vector",
+ dimension: knn_options[:dimensions]
+ }
+
+ if !distance.nil?
+ space_type =
+ case distance
+ when "cosine"
+ "cosinesimil"
+ when "euclidean"
+ "l2"
+ when "inner_product"
+ "innerproduct"
+ else
+ raise ArgumentError, "Unknown distance: #{distance}"
+ end
+
+ vector_options[:method] = {
+ name: "hnsw",
+ space_type: space_type,
+ engine: "lucene"
+ }
+ end
+
+ mapping[field.to_s] = vector_options
+ else
+ vector_options = {
+ type: "dense_vector",
+ dims: knn_options[:dimensions],
+ index: !distance.nil?
+ }
+
+ if !distance.nil?
+ vector_options[:similarity] =
+ case distance
+ when "cosine"
+ "cosine"
+ when "euclidean"
+ "l2_norm"
+ when "inner_product"
+ "max_inner_product"
+ else
+ raise ArgumentError, "Unknown distance: #{distance}"
+ end
+ end
+
+ mapping[field.to_s] = vector_options
+ end
end
if options[:inheritance]
mapping[:type] = keyword_mapping
end