2121import co .elastic .clients .elasticsearch ._types .query_dsl .Query ;
2222import co .elastic .clients .elasticsearch .core .SearchRequest ;
2323import co .elastic .clients .elasticsearch .core .msearch .MultisearchBody ;
24+ import co .elastic .clients .util .ObjectBuilder ;
2425import lombok .Getter ;
2526import lombok .Setter ;
2627import lombok .extern .slf4j .Slf4j ;
4546import java .util .Set ;
4647import java .util .function .BiFunction ;
4748import java .util .function .Consumer ;
49+ import java .util .function .Function ;
4850
4951/**
5052 * @author zhouhao
@@ -97,10 +99,13 @@ public static Query.Builder applyQueryBuilder(Query.Builder queryBuilder,
9799 Consumer <Term > fParamConverter = paramConverter ;
98100 BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > fNestedConverter = nestedConverter ;
99101
100- queryBuilder .bool (bool -> process (
101- terms ,
102- fParamConverter ,
103- fNestedConverter , bool ));
102+ queryBuilder .bool (bool -> {
103+ if (CollectionUtils .isEmpty (terms )) {
104+ return bool ;
105+ }
106+ TermGroup group = groupTerms (terms );
107+ return group .build (group .getType (), fParamConverter , fNestedConverter , bool );
108+ });
104109
105110 return queryBuilder ;
106111 }
@@ -173,120 +178,55 @@ public static SearchRequest.Builder convertSearchRequestBuilder(
173178 return builder ;
174179 }
175180
176-
177- public static BoolQuery .Builder process (List <Term > terms ,
178- Consumer <Term > consumer ,
179- BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > nestedConverter ,
180- BoolQuery .Builder queryBuilders ) {
181-
182- if (CollectionUtils .isEmpty (terms )) {
183- return queryBuilders ;
184- }
185-
186- for (TermGroup group : groupTerms (terms )) {
187- if (group .type == Term .Type .or ) {
188- for (Term groupTerm : group .getTerms ()) {
189- handleOr (queryBuilders , groupTerm , nestedConverter , consumer );
190- }
191- } else {
192- queryBuilders
193- .should (must ->
194- must .bool (bool -> {
195- for (Term groupTerm : group .getTerms ()) {
196- handleAnd (bool , groupTerm , nestedConverter , consumer );
197- }
198- return bool ;
199- }));
200- }
201-
202- }
203- return queryBuilders ;
204- }
205-
206- private static void handleOr (BoolQuery .Builder queryBuilders ,
207- Term term ,
208- BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > nestedConverter ,
209- Consumer <Term > consumer ) {
210- consumer .accept (term );
211- if (term .getTerms ().isEmpty () && term .getValue () != null ) {
212-
213- queryBuilders
214- .should (should -> applyTerm (term , should , nestedConverter ));
215-
216- } else if (!term .getTerms ().isEmpty ()) {
217-
218- queryBuilders
219- .should (should -> should
220- .bool (bool -> process (term .getTerms (), consumer , nestedConverter , bool )));
221- }
222- }
223-
224- private static Query .Builder applyTerm (Term term , Query .Builder builder , BiFunction <Term , NestedQuery .Builder ,
225- NestedQuery .Builder > converter ) {
181+ private static Query .Builder applyTerm (Term term , Query .Builder builder , BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > converter ) {
226182
227183 if (term .getColumn ().contains ("." )) {
228184 String path = term .getColumn ().split ("[.]" )[0 ];
229185
230- builder .nested (n -> converter
231- .apply (term , n
232- .path (path )
233- .boost (1F )
234- .ignoreUnmapped (false )
235- .query (query -> ElasticSearchTermTypes
236- .lookup (term )
237- .map (type -> type .process (term , query ))
238- .orElse (query )))
239- );
186+ builder .nested (n -> converter .apply (term , n
187+ .path (path )
188+ .boost (1F )
189+ .ignoreUnmapped (false )
190+ .query (query -> ElasticSearchTermTypes
191+ .lookup (term )
192+ .map (type -> type .process (term , query ))
193+ .orElse (query ))));
240194
241195 return builder ;
242196 }
243- return ElasticSearchTermTypes
244- .lookup (term )
245- .map (type -> type .process (term , builder ))
246- .orElse (builder );
197+ return ElasticSearchTermTypes .lookup (term ).map (type -> type .process (term , builder )).orElse (builder );
247198 }
248199
249- private static void handleAnd (BoolQuery .Builder queryBuilders ,
250- Term term ,
251- BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > nestedConverter ,
252- Consumer <Term > consumer ) {
253- consumer .accept (term );
254- if (term .getTerms ().isEmpty () && term .getValue () != null ) {
255-
256- queryBuilders .must (must -> applyTerm (term , must , nestedConverter ));
257-
258- } else if (!term .getTerms ().isEmpty ()) {
259-
260- queryBuilders .must (must -> must .bool (bool -> process (term .getTerms (), consumer , nestedConverter , bool )));
261- }
200+ public static TermGroup groupTerms (List <Term > terms ) {
201+ return groupTerms (terms .get (0 ), terms .subList (1 , terms .size ()), new TermGroup (Term .Type .and ));
262202 }
263203
204+ private static TermGroup groupTerms (Term first , List <Term > others , TermGroup currentGroup ) {
205+ if (first .getValue () != null ) {
206+ currentGroup .addTerm (first );
207+ }
208+ if (!first .getTerms ().isEmpty ()) {
209+ currentGroup .addGroup (groupTerms (first .getTerms ()));
210+ }
264211
265- public static Set <TermGroup > groupTerms (List <Term > terms ) {
266- Set <TermGroup > groups = new HashSet <>();
267- TermGroup currentGroup = null ;
268-
269- for (int i = 0 ; i < terms .size (); i ++) {
270- Term currentTerm = terms .get (i );
271- Term nextTerm = (i + 1 < terms .size ()) ? terms .get (i + 1 ) : null ;
212+ if (CollectionUtils .isEmpty (others )) {
213+ return currentGroup ;
214+ }
272215
273- if (currentTerm .getType () == Term .Type .or ) {
274- if (currentGroup == null || currentGroup .type == Term .Type .and ) {
275- currentGroup = new TermGroup (Term .Type .or );
276- }
277- // 如果下一个Term为"AND",创建一个新分组
278- if (nextTerm != null && nextTerm .getType () == Term .Type .and ) {
279- currentGroup = new TermGroup (Term .Type .and );
280- }
281- } else {
282- if (currentGroup == null ) {
283- currentGroup = new TermGroup (Term .Type .and );
284- }
285- }
286- currentGroup .addTerm (currentTerm );
287- groups .add (currentGroup );
216+ Term current = others .get (0 );
217+ //接下来为or,则新建or分组
218+ if (current .getType () == Term .Type .or ) {
219+ TermGroup oldGroup = currentGroup ;
220+ currentGroup = new TermGroup (Term .Type .or );
221+ //添加之前的分组
222+ currentGroup .addGroup (oldGroup );
223+ //添加后续条件
224+ currentGroup .addGroup (groupTerms (others ));
225+ return currentGroup ;
226+ } else {
227+ //在当前分组继续添加后续条件
228+ return groupTerms (current , others .subList (1 , others .size ()), currentGroup );
288229 }
289- return groups ;
290230 }
291231
292232 @ Getter
@@ -295,16 +235,66 @@ public static class TermGroup {
295235 public TermGroup (Term .Type type ) {
296236 this .type = type ;
297237 this .terms = new ArrayList <>();
238+ this .groups = new ArrayList <>();
298239 }
299240
241+ //只需处理第一层value,下级Term已拆分为group
300242 List <Term > terms ;
301243
302244 Term .Type type ;
303245
246+ List <TermGroup > groups ;
247+
304248 public void addTerm (Term term ) {
305249 terms .add (term );
306250 }
307- }
308251
252+ public void addGroup (TermGroup group ) {
253+ if (group .getType () == type ) {
254+ //同类型平铺
255+ for (Term term : group .getTerms ()) {
256+ addTerm (term );
257+ }
258+ groups .addAll (group .getGroups ());
259+ } else if (group .getTerms ().size () == 1 && group .getGroups ().isEmpty ()) {
260+ //不同类型但只有一个条件,直接添加
261+ addTerm (group .getTerms ().get (0 ));
262+ } else {
263+ groups .add (group );
264+ }
265+ }
266+
267+ public BoolQuery .Builder buildByType (Term .Type type , BoolQuery .Builder queryBuilders , Function <Query .Builder , ObjectBuilder <Query >> fn ) {
268+ if (type == Term .Type .and ) {
269+ return queryBuilders .must (fn );
270+ } else {
271+ return queryBuilders .should (fn );
272+ }
273+ }
274+
275+ public BoolQuery .Builder build (Term .Type type ,
276+ Consumer <Term > consumer ,
277+ BiFunction <Term , NestedQuery .Builder , NestedQuery .Builder > nestedConverter ,
278+ BoolQuery .Builder queryBuilders ) {
279+ return buildByType (type , queryBuilders , builder -> builder .bool (_b -> {
280+ if (!terms .isEmpty ()) {
281+ for (Term term : terms ) {
282+ consumer .accept (term );
283+ buildByType (this .getType (), _b , __b -> {
284+ consumer .accept (term );
285+ return applyTerm (term , __b , nestedConverter );
286+ });
287+ }
288+
289+ }
290+ if (!groups .isEmpty ()) {
291+ for (TermGroup group : groups ) {
292+ group .build (this .getType (), consumer , nestedConverter , _b );
293+ }
294+ }
309295
296+ return _b ;
297+ }));
298+ }
299+ }
310300}
0 commit comments