@@ -221,6 +221,13 @@ public function scopeEncryptedExact(Builder $query, string $field, string $term)
221221
222222 $ token = Tokens::exact ($ normalized , $ pepper );
223223
224+ // Check if Elasticsearch is enabled
225+ if (config ('encrypted-search.elasticsearch.enabled ' , false )) {
226+ $ modelIds = $ this ->searchElasticsearch ($ field , $ token , 'exact ' );
227+ return $ query ->whereIn ($ this ->getQualifiedKeyName (), $ modelIds );
228+ }
229+
230+ // Fallback to database
224231 return $ query ->whereIn ($ this ->getQualifiedKeyName (), function ($ sub ) use ($ field , $ token ) {
225232 $ sub ->select ('model_id ' )
226233 ->from ('encrypted_search_index ' )
@@ -254,6 +261,13 @@ public function scopeEncryptedPrefix(Builder $query, string $field, string $term
254261 $ pepper
255262 );
256263
264+ // Check if Elasticsearch is enabled
265+ if (config ('encrypted-search.elasticsearch.enabled ' , false )) {
266+ $ modelIds = $ this ->searchElasticsearch ($ field , $ tokens , 'prefix ' );
267+ return $ query ->whereIn ($ this ->getQualifiedKeyName (), $ modelIds );
268+ }
269+
270+ // Fallback to database
257271 return $ query ->whereIn ($ this ->getQualifiedKeyName (), function ($ sub ) use ($ field , $ tokens ) {
258272 $ sub ->select ('model_id ' )
259273 ->from ('encrypted_search_index ' )
@@ -264,6 +278,53 @@ public function scopeEncryptedPrefix(Builder $query, string $field, string $term
264278 });
265279 }
266280
281+ /**
282+ * Search for model IDs in Elasticsearch based on token(s).
283+ *
284+ * @param string $field
285+ * @param string|array<int, string> $tokens Single token or array of tokens
286+ * @param string $type Either 'exact' or 'prefix'
287+ * @return array<int, mixed> Array of model IDs
288+ */
289+ protected function searchElasticsearch (string $ field , $ tokens , string $ type ): array
290+ {
291+ $ index = config ('encrypted-search.elasticsearch.index ' , 'encrypted_search ' );
292+ $ service = app (ElasticsearchService::class);
293+
294+ // Normalize tokens to array
295+ $ tokenArray = is_array ($ tokens ) ? $ tokens : [$ tokens ];
296+
297+ // Build Elasticsearch query
298+ $ query = [
299+ 'query ' => [
300+ 'bool ' => [
301+ 'must ' => [
302+ ['term ' => ['model_type.keyword ' => static ::class]],
303+ ['term ' => ['field.keyword ' => $ field ]],
304+ ['term ' => ['type.keyword ' => $ type ]],
305+ ['terms ' => ['token.keyword ' => $ tokenArray ]],
306+ ],
307+ ],
308+ ],
309+ '_source ' => ['model_id ' ],
310+ 'size ' => 10000 ,
311+ ];
312+
313+ try {
314+ $ results = $ service ->search ($ index , $ query );
315+
316+ // Extract unique model IDs from results
317+ return collect ($ results )
318+ ->pluck ('_source.model_id ' )
319+ ->unique ()
320+ ->values ()
321+ ->toArray ();
322+ } catch (\Throwable $ e ) {
323+ logger ()->warning ('[EncryptedSearch] Elasticsearch search failed: ' . $ e ->getMessage ());
324+ return [];
325+ }
326+ }
327+
267328 /**
268329 * Resolve the encrypted search configuration for this model.
269330 *
0 commit comments