search-engine-for-typesense 30.1.6.1 → 30.1.6.2
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 +4 -4
- data/lib/search_engine/base/model_dsl.rb +3 -1
- data/lib/search_engine/mapper.rb +1 -1
- data/lib/search_engine/schema.rb +36 -8
- data/lib/search_engine/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea3e7da2359ce1d9b4990147c6627e00a726cfa4e75cc340649ae561b32e42fe
|
|
4
|
+
data.tar.gz: 6b14b6b9e39cab91210e16ecced55f19948831d9f949cb2969f0be5731229cf1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c2252a8d88ebe47b54bb7ac7ed2d65f2e0ed82b3e011ffeb3f5fb3756bff75de417c055a1de8c71fa513e51a6cfcb70b1025e6463164ff5de7018b1fcec1df8
|
|
7
|
+
data.tar.gz: 5519c44a440ed906df1673baf2682b1630171c0a2efb103feeb3300700d2d2653d521432fa332d2bc344c2cf717ba0ae7aa4d3feaaa6dcc7c82cfc0ba1486a4f
|
|
@@ -96,7 +96,9 @@ module SearchEngine
|
|
|
96
96
|
#
|
|
97
97
|
# @param name [#to_sym]
|
|
98
98
|
# @param type [Object] type descriptor (e.g., :string, :integer)
|
|
99
|
-
# @param index [Boolean, nil] when false, omit from compiled Typesense schema (still
|
|
99
|
+
# @param index [Boolean, nil] when false, omit from compiled Typesense schema (still
|
|
100
|
+
# hydrated/displayed). Fields referenced by an embedding's `from:` are kept in the
|
|
101
|
+
# schema with Typesense-native `"index": false` instead of being omitted entirely.
|
|
100
102
|
# @param locale [String, nil]
|
|
101
103
|
# @param optional [Boolean, nil]
|
|
102
104
|
# @param sort [Boolean, nil]
|
data/lib/search_engine/mapper.rb
CHANGED
|
@@ -566,7 +566,7 @@ module SearchEngine
|
|
|
566
566
|
base_fields.reject! { |fname| fname.to_s.include?('.') }
|
|
567
567
|
required = base_fields.to_set
|
|
568
568
|
opts.each do |fname, o|
|
|
569
|
-
next unless o.is_a?(Hash) && o[:optional]
|
|
569
|
+
next unless o.is_a?(Hash) && (o[:optional] || o[:index] == false)
|
|
570
570
|
|
|
571
571
|
required.delete(fname.to_sym)
|
|
572
572
|
end
|
data/lib/search_engine/schema.rb
CHANGED
|
@@ -35,7 +35,7 @@ module SearchEngine
|
|
|
35
35
|
}.freeze
|
|
36
36
|
|
|
37
37
|
FIELD_COMPARE_KEYS = %i[
|
|
38
|
-
type reference async_reference locale sort optional infix facet
|
|
38
|
+
type reference async_reference locale sort optional index infix facet
|
|
39
39
|
embed num_dim hnsw_params
|
|
40
40
|
].freeze
|
|
41
41
|
PHYSICAL_SUFFIX_RE = /_\d{8}_\d{6}_\d{3}\z/
|
|
@@ -44,9 +44,14 @@ module SearchEngine
|
|
|
44
44
|
# Build a Typesense-compatible schema hash from a model class DSL.
|
|
45
45
|
#
|
|
46
46
|
# The output includes only keys that are supported and declared via the DSL.
|
|
47
|
-
# Fields explicitly marked with `index: false` are
|
|
48
|
-
#
|
|
49
|
-
#
|
|
47
|
+
# Fields explicitly marked with `index: false` are generally omitted from
|
|
48
|
+
# the compiled schema (they can still be sent in documents and will be
|
|
49
|
+
# hydrated/displayed, but are not indexed in memory).
|
|
50
|
+
#
|
|
51
|
+
# **Exception:** fields with `index: false` that are referenced by an
|
|
52
|
+
# embedding's `from:` list are included with Typesense-native
|
|
53
|
+
# `"index": false` and `"optional": true` so the embedding model can
|
|
54
|
+
# read their values without keyword-indexing them.
|
|
50
55
|
#
|
|
51
56
|
# @param klass [Class] model class inheriting from {SearchEngine::Base}
|
|
52
57
|
# @return [Hash] frozen schema hash with symbol keys
|
|
@@ -462,6 +467,7 @@ module SearchEngine
|
|
|
462
467
|
attribute_options = klass.respond_to?(:attribute_options) ? (klass.attribute_options || {}) : {}
|
|
463
468
|
references_by_local_key = build_references_by_local_key(klass, client: client)
|
|
464
469
|
async_reference_by_local_key = build_async_reference_by_local_key(klass)
|
|
470
|
+
embed_source_fields = collect_embed_source_fields(attribute_options)
|
|
465
471
|
|
|
466
472
|
fields_array = []
|
|
467
473
|
needs_nested_fields = false
|
|
@@ -470,14 +476,16 @@ module SearchEngine
|
|
|
470
476
|
validate_attribute_type!(attribute_name, type_descriptor)
|
|
471
477
|
|
|
472
478
|
opts = attribute_options[attribute_name.to_sym] || {}
|
|
473
|
-
# Skip non-indexed attributes and any nested fields under a non-indexed base
|
|
479
|
+
# Skip non-indexed attributes and any nested fields under a non-indexed base,
|
|
480
|
+
# unless the field is referenced by an embedding's from: list.
|
|
474
481
|
base_index_false = false
|
|
475
482
|
if attribute_name.to_s.include?('.')
|
|
476
483
|
base_sym = attribute_name.to_s.split('.', 2).first.to_sym
|
|
477
484
|
base_opts = attribute_options[base_sym] || {}
|
|
478
485
|
base_index_false = (base_opts[:index] == false)
|
|
479
486
|
end
|
|
480
|
-
|
|
487
|
+
effectively_unindexed = opts[:index] == false || base_index_false
|
|
488
|
+
next if effectively_unindexed && !embed_source_fields.include?(attribute_name.to_sym)
|
|
481
489
|
|
|
482
490
|
ts_type = typesense_type_for(type_descriptor)
|
|
483
491
|
|
|
@@ -536,14 +544,34 @@ module SearchEngine
|
|
|
536
544
|
%w[object object[]].include?(ts_type)
|
|
537
545
|
end
|
|
538
546
|
|
|
547
|
+
# Collect field names referenced by any embedding's from: list.
|
|
548
|
+
# @param attribute_options [Hash] model attribute options
|
|
549
|
+
# @return [Set<Symbol>] field names used as embedding sources
|
|
550
|
+
def collect_embed_source_fields(attribute_options)
|
|
551
|
+
sources = Set.new
|
|
552
|
+
attribute_options.each_value do |opts|
|
|
553
|
+
next unless opts.is_a?(Hash)
|
|
554
|
+
|
|
555
|
+
embed = opts[:embed]
|
|
556
|
+
next unless embed.is_a?(Hash)
|
|
557
|
+
|
|
558
|
+
from = embed[:from] || embed['from']
|
|
559
|
+
Array(from).each { |f| sources << f.to_sym }
|
|
560
|
+
end
|
|
561
|
+
sources
|
|
562
|
+
end
|
|
563
|
+
private :collect_embed_source_fields
|
|
564
|
+
|
|
539
565
|
def build_field_entry(attribute_name, ts_type, references_by_local_key, async_reference_by_local_key, opts)
|
|
566
|
+
unindexed = opts[:index] == false
|
|
540
567
|
{
|
|
541
568
|
name: attribute_name.to_s,
|
|
542
569
|
type: ts_type,
|
|
543
570
|
**{
|
|
571
|
+
index: unindexed ? false : nil,
|
|
544
572
|
locale: opts[:locale],
|
|
545
573
|
sort: opts[:sort],
|
|
546
|
-
optional: opts[:optional],
|
|
574
|
+
optional: unindexed ? true : opts[:optional],
|
|
547
575
|
infix: opts[:infix],
|
|
548
576
|
facet: opts[:facet],
|
|
549
577
|
reference: references_by_local_key[attribute_name.to_sym],
|
|
@@ -621,7 +649,7 @@ module SearchEngine
|
|
|
621
649
|
entry = { name: fname, type: normalize_type(ftype) }
|
|
622
650
|
entry[:reference] = fref.to_s unless fref.nil? || fref.to_s.strip.empty?
|
|
623
651
|
|
|
624
|
-
%i[locale sort optional infix facet async_reference].each do |k|
|
|
652
|
+
%i[locale sort optional index infix facet async_reference].each do |k|
|
|
625
653
|
val = field[k] || field[k.to_s]
|
|
626
654
|
entry[k] = val unless val.nil?
|
|
627
655
|
end
|