1+ // ignore_for_file: cascade_invocations
2+
13import 'package:ht_data_client/ht_data_client.dart' ;
24import 'package:ht_data_mongodb/src/mongo_db_connection_manager.dart' ;
35import 'package:ht_shared/ht_shared.dart' ;
@@ -66,6 +68,7 @@ class HtDataMongodb<T> implements HtDataClient<T> {
6668 required String modelName,
6769 required FromJson <T > fromJson,
6870 required ToJson <T > toJson,
71+ this .searchableFields,
6972 Logger ? logger,
7073 }) : _connectionManager = connectionManager,
7174 _modelName = modelName,
@@ -74,6 +77,7 @@ class HtDataMongodb<T> implements HtDataClient<T> {
7477 _logger = logger ?? Logger ('HtDataMongodb<$T >' );
7578
7679 final MongoDbConnectionManager _connectionManager;
80+ final List <String >? searchableFields;
7781 final String _modelName;
7882 final FromJson <T > _fromJson;
7983 final ToJson <T > _toJson;
@@ -147,11 +151,39 @@ class HtDataMongodb<T> implements HtDataClient<T> {
147151 final processedFilter = Map <String , dynamic >.from (filter);
148152
149153 // Check for the special 'q' parameter for text search.
150- if (processedFilter.containsKey ('q' )) {
151- final searchTerm = processedFilter.remove ('q' );
152- // Add the MongoDB text search operator.
153- // This assumes a text index exists on the collection.
154- processedFilter[r'$text' ] = {r'$search' : searchTerm};
154+ if (processedFilter.containsKey ('q' ) &&
155+ searchableFields != null &&
156+ searchableFields! .isNotEmpty) {
157+ final searchTerm = processedFilter.remove ('q' ) as String ;
158+ final searchConditions = < Map <String , dynamic >> [];
159+
160+ for (final field in searchableFields! ) {
161+ searchConditions.add ({
162+ field: {r'$regex' : searchTerm, r'$options' : 'i' },
163+ });
164+ }
165+
166+ // If there's already an '$and' operator, add the '$or' to it.
167+ // Otherwise, create a new '$and' that includes the '$or'.
168+ if (processedFilter.containsKey (r'$and' )) {
169+ final existingAnd = processedFilter[r'$and' ] as List ;
170+ existingAnd.add ({r'$or' : searchConditions});
171+ } else {
172+ // If there are other filters, they need to be combined with the search.
173+ final otherFilters = Map <String , dynamic >.from (processedFilter);
174+ processedFilter.clear ();
175+ processedFilter[r'$and' ] = [
176+ otherFilters,
177+ {r'$or' : searchConditions}
178+ ];
179+ }
180+ } else if (processedFilter.containsKey ('q' )) {
181+ // If 'q' is present but no searchable fields are configured,
182+ // remove it to prevent errors.
183+ processedFilter.remove ('q' );
184+ _logger.warning (
185+ 'Search term "q" was provided, but no searchableFields are configured for $_modelName . Ignoring search term.' ,
186+ );
155187 }
156188
157189 // If there's only one filter condition after processing, return it directly.
0 commit comments