44
55use DirectoryTree \OpenSearchAdapter \Search \SearchRequest as OpenSearchRequest ;
66use DirectoryTree \OpenSearchScoutDriver \SearchRequest ;
7- use Illuminate \Contracts \Support \Arrayable ;
7+ use DirectoryTree \OpenSearchScoutDriver \SearchRequestPayload ;
8+ use DirectoryTree \OpenSearchScoutDriver \SearchRequestPayloadInterface ;
89use Laravel \Scout \Builder ;
9- use stdClass ;
1010
1111/**
1212 * Creates OpenSearch search requests from Scout builders.
@@ -20,78 +20,41 @@ class SearchRequestFactory implements SearchRequestFactoryInterface
2020 */
2121 public function makeFromBuilder (Builder $ builder , array $ options = []): SearchRequest
2222 {
23- if ($ compiled = $ this ->compileBuilder ($ builder , $ options )) {
24- return $ this ->makeFromCompiled ($ builder , $ compiled );
25- }
26-
27- $ request = new OpenSearchRequest ($ this ->makeQuery ($ builder ));
28-
29- if ($ sort = $ this ->makeSort ($ builder )) {
30- $ request ->sort ($ sort );
31- }
32-
33- if (! is_null ($ from = $ this ->makeFrom ($ options ))) {
34- $ request ->from ($ from );
35- }
36-
37- if (! is_null ($ size = $ this ->makeSize ($ builder , $ options ))) {
38- $ request ->size ($ size );
39- }
23+ $ payload = $ builder instanceof SearchRequestPayloadInterface
24+ ? $ builder ->toSearchRequestPayload ($ options )
25+ : SearchRequestPayload::fromBuilder ($ builder , $ options );
4026
41- $ this ->applyOptions ($ request , $ builder ->options );
42-
43- return new SearchRequest ($ this ->makeIndex ($ builder ), $ request );
27+ return $ this ->makeFromPayload ($ builder , $ payload );
4428 }
4529
4630 /**
47- * Make an OpenSearch request from a compiled builder payload.
48- *
49- * @param array{query?: array<string, mixed>|null, sort?: array<int|string, mixed>|null, from?: int|null, size?: int|string|null, aggs?: array<string, mixed>|null, aggregations?: array<string, mixed>|null} $compiled
31+ * Make an OpenSearch request from a builder payload.
5032 */
51- protected function makeFromCompiled (Builder $ builder , array $ compiled ): SearchRequest
33+ protected function makeFromPayload (Builder $ builder , SearchRequestPayload $ payload ): SearchRequest
5234 {
53- $ request = new OpenSearchRequest ($ compiled ['query ' ] ?? []);
54-
55- if (! empty ($ compiled ['sort ' ])) {
56- $ request ->sort ($ compiled ['sort ' ]);
57- }
35+ $ request = new OpenSearchRequest ($ payload ->query ());
5836
59- if (! empty ( $ compiled [ ' from ' ] )) {
60- $ request ->from (( int ) $ compiled [ ' from ' ] );
37+ if ($ sort = $ payload -> sort ( )) {
38+ $ request ->sort ( $ sort );
6139 }
6240
63- if (isset ( $ compiled [ ' size ' ]) && is_numeric ( $ compiled [ ' size ' ] )) {
64- $ request ->size (( int ) $ compiled [ ' size ' ] );
41+ if (! is_null ( $ from = $ payload -> from () )) {
42+ $ request ->from ( $ from );
6543 }
6644
67- if (! empty ( $ compiled [ ' aggs ' ] )) {
68- $ request ->aggregations ( $ compiled [ ' aggs ' ] );
45+ if (! is_null ( $ size = $ payload -> size () )) {
46+ $ request ->size ( $ size );
6947 }
7048
71- if (! empty ( $ compiled [ ' aggregations ' ] )) {
72- $ request ->aggregations ($ compiled [ ' aggregations ' ] );
49+ if ($ aggregations = $ payload -> aggregations ( )) {
50+ $ request ->aggregations ($ aggregations );
7351 }
7452
7553 $ this ->applyOptions ($ request , $ builder ->options );
7654
7755 return new SearchRequest ($ this ->makeIndex ($ builder ), $ request );
7856 }
7957
80- /**
81- * Compile builders that expose their own OpenSearch payload.
82- *
83- * @param array<string, mixed> $options
84- * @return array<string, mixed>|null
85- */
86- protected function compileBuilder (Builder $ builder , array $ options ): ?array
87- {
88- if (! $ builder instanceof Arrayable) {
89- return null ;
90- }
91-
92- return $ builder ->toArray ($ options );
93- }
94-
9558 /**
9659 * Get the OpenSearch index name for the builder.
9760 */
@@ -100,106 +63,6 @@ protected function makeIndex(Builder $builder): string
10063 return $ builder ->index ?: $ builder ->model ->searchableAs ();
10164 }
10265
103- /**
104- * Create the OpenSearch query body.
105- *
106- * @return array<string, mixed>
107- */
108- protected function makeQuery (Builder $ builder ): array
109- {
110- $ query = [
111- 'bool ' => [],
112- ];
113-
114- if (! empty ($ builder ->query )) {
115- $ query ['bool ' ]['must ' ] = [
116- 'query_string ' => [
117- 'query ' => $ builder ->query ,
118- ],
119- ];
120- } else {
121- $ query ['bool ' ]['must ' ] = [
122- 'match_all ' => new stdClass ,
123- ];
124- }
125-
126- if ($ filter = $ this ->makeFilter ($ builder )) {
127- $ query ['bool ' ]['filter ' ] = $ filter ;
128- }
129-
130- return $ query ;
131- }
132-
133- /**
134- * Create the OpenSearch filter clauses.
135- *
136- * @return array<int, array<string, mixed>>|null
137- */
138- protected function makeFilter (Builder $ builder ): ?array
139- {
140- $ filter = [];
141-
142- foreach ($ builder ->wheres as $ field => $ value ) {
143- if (is_array ($ value ) && isset ($ value ['field ' ], $ value ['value ' ])) {
144- $ filter [] = ['term ' => [$ value ['field ' ] => $ value ['value ' ]]];
145-
146- continue ;
147- }
148-
149- $ filter [] = ['term ' => [$ field => $ value ]];
150- }
151-
152- if (property_exists ($ builder , 'whereIns ' )) {
153- foreach ($ builder ->whereIns as $ field => $ values ) {
154- $ filter [] = ['terms ' => [$ field => $ values ]];
155- }
156- }
157-
158- return empty ($ filter ) ? null : $ filter ;
159- }
160-
161- /**
162- * Create the OpenSearch sort clauses.
163- *
164- * @return array<int, array<string, string>>|null
165- */
166- protected function makeSort (Builder $ builder ): ?array
167- {
168- $ sort = [];
169-
170- foreach ($ builder ->orders as $ order ) {
171- $ sort [] = [$ order ['column ' ] => $ order ['direction ' ]];
172- }
173-
174- return empty ($ sort ) ? null : $ sort ;
175- }
176-
177- /**
178- * Create the OpenSearch result offset.
179- *
180- * @param array{page?: int, perPage?: int} $options
181- */
182- protected function makeFrom (array $ options ): ?int
183- {
184- if (isset ($ options ['page ' ], $ options ['perPage ' ])) {
185- return ($ options ['page ' ] - 1 ) * $ options ['perPage ' ];
186- }
187-
188- return null ;
189- }
190-
191- /**
192- * Create the OpenSearch result size.
193- *
194- * @param array{perPage?: int} $options
195- */
196- protected function makeSize (Builder $ builder , array $ options ): ?int
197- {
198- $ size = $ options ['perPage ' ] ?? $ builder ->limit ;
199-
200- return is_numeric ($ size ) ? (int ) $ size : null ;
201- }
202-
20366 /**
20467 * Apply Scout builder options to the OpenSearch search request.
20568 *
@@ -255,12 +118,12 @@ protected function applyOptions(OpenSearchRequest $request, array $options): voi
255118 $ request ->source ($ options ['_source ' ]);
256119 }
257120
258- if (array_key_exists ('track_total_hits ' , $ options )) {
259- $ request ->trackTotalHits ($ options ['track_total_hits ' ]);
260- }
261-
262121 if (array_key_exists ('track_scores ' , $ options )) {
263122 $ request ->trackScores ($ options ['track_scores ' ]);
264123 }
124+
125+ if (array_key_exists ('track_total_hits ' , $ options )) {
126+ $ request ->trackTotalHits ($ options ['track_total_hits ' ]);
127+ }
265128 }
266129}
0 commit comments