1616package org .eclipse .jnosql .databases .elasticsearch .communication ;
1717
1818
19+ import co .elastic .clients .elasticsearch .ElasticsearchClient ;
20+ import co .elastic .clients .elasticsearch ._types .mapping .Property ;
1921import co .elastic .clients .elasticsearch ._types .query_dsl .BoolQuery ;
22+ import co .elastic .clients .elasticsearch ._types .query_dsl .MatchQuery ;
2023import co .elastic .clients .elasticsearch ._types .query_dsl .Query ;
2124import co .elastic .clients .elasticsearch ._types .query_dsl .QueryStringQuery ;
2225import co .elastic .clients .elasticsearch ._types .query_dsl .RangeQuery ;
2326import co .elastic .clients .elasticsearch ._types .query_dsl .TermQuery ;
27+ import co .elastic .clients .elasticsearch .indices .get_mapping .IndexMappingRecord ;
2428import co .elastic .clients .json .JsonData ;
2529import org .eclipse .jnosql .communication .Condition ;
2630import org .eclipse .jnosql .communication .TypeReference ;
2933import org .eclipse .jnosql .communication .document .DocumentQuery ;
3034import org .eclipse .jnosql .communication .driver .ValueUtil ;
3135
32- import java .util . ArrayList ;
36+ import java .io . IOException ;
3337import java .util .EnumSet ;
3438import java .util .List ;
39+ import java .util .Map ;
3540import java .util .Objects ;
3641import java .util .Optional ;
3742import java .util .Set ;
3843import java .util .stream .Stream ;
3944
40- import static org .eclipse .jnosql .communication .Condition .EQUALS ;
4145import static org .eclipse .jnosql .communication .Condition .IN ;
4246
4347final class QueryConverter {
@@ -47,17 +51,25 @@ final class QueryConverter {
4751 private QueryConverter () {
4852 }
4953
50- static QueryConverterResult select (DocumentQuery query ) {
51- List <String > ids = new ArrayList <>();
54+ static QueryConverterResult select (ElasticsearchClient client , String database , DocumentQuery query ) {
55+
56+ var indexMappingRecord = getIndexMappingRecord (client , database , query );
5257
5358 Query .Builder nameCondition = Optional .of (query .name ())
54- .map (collection -> new Query .Builder ().term (q -> q
55- .field (EntityConverter .ENTITY ).value (collection )))
59+ .map (collection -> {
60+ if (supportTermQuery (indexMappingRecord , EntityConverter .ENTITY )) {
61+ return new Query .Builder ().term (q -> q
62+ .field (EntityConverter .ENTITY ).value (collection ));
63+ }
64+ return new Query .Builder ().match (q -> q
65+ .field (EntityConverter .ENTITY ).query (collection ));
66+
67+ })
5668 .map (Query .Builder .class ::cast )
5769 .orElse (null );
5870
5971 Query .Builder queryConditions = query .condition ()
60- .map (c -> getCondition (c , ids ))
72+ .map (c -> getCondition (indexMappingRecord , c ))
6173 .orElse (null );
6274
6375
@@ -67,31 +79,55 @@ static QueryConverterResult select(DocumentQuery query) {
6779 .must (c1 .build (), c2 .build ()))))
6880 .orElse (null );
6981
70- return new QueryConverterResult (builder , ids );
82+ return new QueryConverterResult (builder );
7183
7284 }
7385
86+ public static boolean supportTermQuery (IndexMappingRecord indexMappingRecord , String attribute ) {
87+ return supportTermQuery (indexMappingRecord .mappings ().properties (), attribute );
88+ }
7489
75- private static Query .Builder getCondition (DocumentCondition condition , List <String > ids ) {
76- Document document = condition .document ();
77-
78- if (!NOT_APPENDABLE .contains (condition .condition ()) && isIdField (document )) {
79- if (IN .equals (condition .condition ())) {
80- ids .addAll (document .get (new TypeReference <List <String >>() {
81- }));
82- } else if (EQUALS .equals (condition .condition ())) {
83- ids .add (document .get (String .class ));
90+ public static boolean supportTermQuery (Map <String , Property > properties , String attribute ) {
91+ String attributeName = attribute ;
92+ if (attributeName .contains ("." )) {
93+ attributeName = attribute .substring (0 , attribute .indexOf ("." ));
94+ Property property = properties .get (attributeName );
95+ if (Objects .nonNull (property ) && property .isObject ()) {
96+ return supportTermQuery (property .object ().properties (),
97+ attribute .substring (attribute .indexOf ("." ) + 1 ));
8498 }
99+ return false ;
100+ }
101+ Property property = properties .get (attributeName );
102+ return Objects .nonNull (property ) && property .isKeyword ();
103+ }
85104
86- return null ;
105+ private static IndexMappingRecord getIndexMappingRecord (ElasticsearchClient client , String database , DocumentQuery query ) {
106+ try {
107+ return client .indices ().getMapping (q -> q .index (database ))
108+ .get (database );
109+ } catch (IOException e ) {
110+ throw new IllegalStateException ("cannot retrieve the index's mapping: %s" .formatted (e .getMessage ()), e );
87111 }
112+ }
113+
114+
115+ private static Query .Builder getCondition (IndexMappingRecord indexMappingRecord , DocumentCondition condition ) {
116+ Document document = condition .document ();
88117
89118 switch (condition .condition ()) {
90119 case EQUALS :
120+ if (supportTermQuery (indexMappingRecord , document .name ())) {
121+ return (Query .Builder ) new Query .Builder ()
122+ .term (TermQuery .of (tq -> tq
123+ .field (document .name ())
124+ .value (v -> v
125+ .anyValue (JsonData .of (document .value ().get ())))));
126+ }
91127 return (Query .Builder ) new Query .Builder ()
92- .term ( TermQuery .of (tq -> tq
128+ .match ( MatchQuery .of (tq -> tq
93129 .field (document .name ())
94- .value (v -> v
130+ .query (v -> v
95131 .anyValue (JsonData .of (document .value ().get ())))));
96132 case LESSER_THAN :
97133 return (Query .Builder ) new Query .Builder ()
@@ -122,10 +158,18 @@ private static Query.Builder getCondition(DocumentCondition condition, List<Stri
122158 case IN :
123159 return (Query .Builder ) ValueUtil .convertToList (document .value ())
124160 .stream ()
125- .map (val -> new Query .Builder ()
126- .term (TermQuery .of (tq -> tq
127- .field (document .name ())
128- .value (v -> v .anyValue (JsonData .of (val ))))))
161+ .map (val -> {
162+ if (supportTermQuery (indexMappingRecord , document .name ())) {
163+ return new Query .Builder ()
164+ .term (TermQuery .of (tq -> tq
165+ .field (document .name ())
166+ .value (v -> v .anyValue (JsonData .of (val )))));
167+ }
168+ return new Query .Builder ()
169+ .match (MatchQuery .of (tq -> tq
170+ .field (document .name ())
171+ .query (v -> v .anyValue (JsonData .of (val )))));
172+ })
129173 .reduce ((d1 , d2 ) -> new Query .Builder ()
130174 .bool (BoolQuery .of (bq -> bq
131175 .should (List .of (d1 .build (), d2 .build ())))))
@@ -134,7 +178,7 @@ private static Query.Builder getCondition(DocumentCondition condition, List<Stri
134178 return document .get (new TypeReference <List <DocumentCondition >>() {
135179 })
136180 .stream ()
137- .map (d -> getCondition (d , ids ))
181+ .map (d -> getCondition (indexMappingRecord , d ))
138182 .filter (Objects ::nonNull )
139183 .reduce ((d1 , d2 ) -> (Query .Builder ) new Query .Builder ()
140184 .bool (BoolQuery .of (bq -> bq
@@ -145,15 +189,15 @@ private static Query.Builder getCondition(DocumentCondition condition, List<Stri
145189 return document .get (new TypeReference <List <DocumentCondition >>() {
146190 })
147191 .stream ()
148- .map (d -> getCondition (d , ids ))
192+ .map (d -> getCondition (indexMappingRecord , d ))
149193 .filter (Objects ::nonNull )
150194 .reduce ((d1 , d2 ) -> (Query .Builder ) new Query .Builder ()
151195 .bool (BoolQuery .of (bq -> bq
152196 .should (List .of (d1 .build (), d2 .build ())))))
153197 .orElseThrow (() -> new IllegalStateException ("An and condition cannot be empty" ));
154198 case NOT :
155199 DocumentCondition dc = document .get (DocumentCondition .class );
156- Query .Builder queryBuilder = Optional .ofNullable (getCondition (dc , ids ))
200+ Query .Builder queryBuilder = Optional .ofNullable (getCondition (indexMappingRecord , dc ))
157201 .orElseThrow (() -> new IllegalStateException ("An and condition cannot be empty" ));
158202 return (Query .Builder ) new Query .Builder ()
159203 .bool (BoolQuery .of (bq -> bq
0 commit comments