Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 112 additions & 2 deletions lib/src/models/field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,39 @@ class Field {
/// Example value: `ReferencedCollectionName.fieldName`.
final String? reference;

/// Enable stemming for this string field.
final bool stem;

/// Whether to store the field value on disk.
///
/// When set to `false`, the field value won't be stored on disk.
final bool store;

/// Enable range index for this numerical field.
///
/// Useful for efficient range queries on numerical fields.
final bool rangeIndex;

/// List of characters to use as token separators for this field.
///
/// Overrides the collection-level token_separators setting for this field.
final List<String>? tokenSeparators;

/// List of special characters to index as part of tokens for this field.
///
/// Overrides the collection-level symbols_to_index setting for this field.
final List<String>? symbolsToIndex;

/// Custom stem dictionary for this field.
///
/// Allows specifying custom stemming rules for this field.
final String? stemDictionary;

/// Maximum length to truncate the field value to.
///
/// Token values longer than this will be truncated.
final int? truncateLen;

Field(
this.name, {
this.type,
Expand All @@ -60,6 +93,13 @@ class Field {
this.sort = false,
this.enableInfixSearch = false,
this.reference,
this.stem = false,
this.store = true,
this.rangeIndex = false,
this.tokenSeparators,
this.symbolsToIndex,
this.stemDictionary,
this.truncateLen,
}) {
if (name.isEmpty) {
throw ArgumentError('Ensure Field.name is not empty');
Expand All @@ -84,6 +124,13 @@ class Field {
sort: map['sort'] ?? false,
enableInfixSearch: map['infix'] ?? false,
reference: map['reference'],
stem: map['stem'] ?? false,
store: map['store'] ?? true,
rangeIndex: map['range_index'] ?? false,
tokenSeparators: (map['token_separators'] as List?)?.cast<String>(),
symbolsToIndex: (map['symbols_to_index'] as List?)?.cast<String>(),
stemDictionary: map['stem_dictionary'],
truncateLen: map['truncate_len'],
);
}

Expand Down Expand Up @@ -117,6 +164,27 @@ class Field {
if (reference != null) {
map['reference'] = reference;
}
if (stem) {
map['stem'] = true;
}
if (!store) {
map['store'] = false;
}
if (rangeIndex) {
map['range_index'] = true;
}
if (tokenSeparators != null) {
map['token_separators'] = tokenSeparators;
}
if (symbolsToIndex != null) {
map['symbols_to_index'] = symbolsToIndex;
}
if (stemDictionary != null && stemDictionary!.isNotEmpty) {
map['stem_dictionary'] = stemDictionary;
}
if (truncateLen != null) {
map['truncate_len'] = truncateLen;
}
return map;
}

Expand All @@ -137,7 +205,14 @@ class Field {
locale.hashCode ^
sort.hashCode ^
enableInfixSearch.hashCode ^
reference.hashCode;
reference.hashCode ^
stem.hashCode ^
store.hashCode ^
rangeIndex.hashCode ^
tokenSeparators.hashCode ^
symbolsToIndex.hashCode ^
stemDictionary.hashCode ^
truncateLen.hashCode;

@override
bool operator ==(Object other) {
Expand All @@ -153,8 +228,25 @@ class Field {
other.locale == locale &&
other.sort == sort &&
other.enableInfixSearch == enableInfixSearch &&
other.reference == reference;
other.reference == reference &&
other.stem == stem &&
other.store == store &&
other.rangeIndex == rangeIndex &&
_listEquals(other.tokenSeparators, tokenSeparators) &&
_listEquals(other.symbolsToIndex, symbolsToIndex) &&
other.stemDictionary == stemDictionary &&
other.truncateLen == truncateLen;
}
}

bool _listEquals<T>(List<T>? a, List<T>? b) {
if (a == null && b == null) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}

/// Used to update a colletion's fields.
Expand All @@ -177,6 +269,14 @@ class UpdateField extends Field {
super.locale,
super.sort,
super.enableInfixSearch,
super.reference,
super.stem,
super.store,
super.rangeIndex,
super.tokenSeparators,
super.symbolsToIndex,
super.stemDictionary,
super.truncateLen,
this.shouldDrop = false,
});

Expand All @@ -203,6 +303,14 @@ class UpdateField extends Field {
locale: field.locale,
sort: field.sort,
enableInfixSearch: field.enableInfixSearch,
reference: field.reference,
stem: field.stem,
store: field.store,
rangeIndex: field.rangeIndex,
tokenSeparators: field.tokenSeparators,
symbolsToIndex: field.symbolsToIndex,
stemDictionary: field.stemDictionary,
truncateLen: field.truncateLen,
shouldDrop: map['drop'] ?? false,
);
}
Expand Down Expand Up @@ -263,6 +371,7 @@ enum Type {
geopoint,
geopolygon,
object,
image,
}

extension _Type on Type {
Expand All @@ -276,6 +385,7 @@ extension _Type on Type {
case Type.geopoint:
case Type.geopolygon:
case Type.object:
case Type.image:
final description = toString(),
indexOfDot = description.indexOf('.'),
value = description.substring(indexOfDot + 1);
Expand Down
90 changes: 89 additions & 1 deletion lib/src/models/schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,36 @@ class Schema extends BaseSchema {
/// Boolean to enable nested fields on the schema, only available for typesense 0.24 or more
final bool? enableNestedFields;

/// Timestamp when the collection was created.
final int? createdAt;

/// Number of memory shards used by the collection.
final int? numMemoryShards;

/// List of curation set names associated with this collection.
final List<String>? curationSets;

/// List of synonym set names associated with this collection.
final List<String>? synonymSets;

/// List of special characters to index at the collection level.
final List<String>? symbolsToIndex;

/// List of characters to use as token separators at the collection level.
final List<String>? tokenSeparators;

Schema(
this.name,
super.fields, {
this.defaultSortingField,
this.documentCount,
this.enableNestedFields,
this.createdAt,
this.numMemoryShards,
this.curationSets,
this.synonymSets,
this.symbolsToIndex,
this.tokenSeparators,
});

factory Schema.fromMap(Map<String, dynamic> map) {
Expand Down Expand Up @@ -66,6 +90,12 @@ class Schema extends BaseSchema {
documentCount: map['num_documents'] ?? 0,
defaultSortingField: defaultSortingField,
enableNestedFields: enableNestedFields,
createdAt: map['created_at'],
numMemoryShards: map['num_memory_shards'],
curationSets: (map['curation_sets'] as List?)?.cast<String>(),
synonymSets: (map['synonym_sets'] as List?)?.cast<String>(),
symbolsToIndex: (map['symbols_to_index'] as List?)?.cast<String>(),
tokenSeparators: (map['token_separators'] as List?)?.cast<String>(),
);
}

Expand All @@ -82,12 +112,48 @@ class Schema extends BaseSchema {
if (enableNestedFields != null) {
map['enable_nested_fields'] = enableNestedFields;
}
if (createdAt != null) {
map['created_at'] = createdAt;
}
if (numMemoryShards != null) {
map['num_memory_shards'] = numMemoryShards;
}
if (curationSets != null) {
map['curation_sets'] = curationSets;
}
if (synonymSets != null) {
map['synonym_sets'] = synonymSets;
}
if (symbolsToIndex != null) {
map['symbols_to_index'] = symbolsToIndex;
}
if (tokenSeparators != null) {
map['token_separators'] = tokenSeparators;
}
return map;
}
}

class UpdateSchema extends BaseSchema {
UpdateSchema(Set<UpdateField> super.fields);
/// List of synonym set IDs to associate with the collection.
final List<String>? synonymSets;

/// List of curation set IDs to associate with the collection.
final List<String>? curationSets;

/// List of special characters to index at the collection level.
final List<String>? symbolsToIndex;

/// List of characters to use as token separators at the collection level.
final List<String>? tokenSeparators;

UpdateSchema(
Set<UpdateField> super.fields, {
this.synonymSets,
this.curationSets,
this.symbolsToIndex,
this.tokenSeparators,
});

factory UpdateSchema.fromMap(Map<String, dynamic> map) {
final Set<UpdateField> fields = (map['fields'] != null)
Expand All @@ -98,8 +164,30 @@ class UpdateSchema extends BaseSchema {

return UpdateSchema(
fields,
synonymSets: (map['synonym_sets'] as List?)?.cast<String>(),
curationSets: (map['curation_sets'] as List?)?.cast<String>(),
symbolsToIndex: (map['symbols_to_index'] as List?)?.cast<String>(),
tokenSeparators: (map['token_separators'] as List?)?.cast<String>(),
);
}

@override
Map<String, dynamic> toMap() {
final map = super.toMap();
if (synonymSets != null) {
map['synonym_sets'] = synonymSets;
}
if (curationSets != null) {
map['curation_sets'] = curationSets;
}
if (symbolsToIndex != null) {
map['symbols_to_index'] = symbolsToIndex;
}
if (tokenSeparators != null) {
map['token_separators'] = tokenSeparators;
}
return map;
}
}

ArgumentError _defaultSortingFieldNotInSchema(String name) =>
Expand Down