Skip to content

Commit 6190f70

Browse files
authored
Merge pull request #226 from dearrudam/issues-386
Fix issue #386
2 parents 7a01a22 + b334d82 commit 6190f70

File tree

13 files changed

+934
-98
lines changed

13 files changed

+934
-98
lines changed

jnosql-elasticsearch/src/main/java/org/eclipse/jnosql/databases/elasticsearch/communication/ElasticsearchDocumentConfiguration.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ public void add(Header header) {
8080

8181
@Override
8282
public ElasticsearchDocumentManagerFactory apply(Settings settings) {
83+
ElasticsearchClient elasticsearchClient = buildElasticsearchClient(settings);
84+
85+
return new ElasticsearchDocumentManagerFactory(elasticsearchClient);
86+
}
87+
88+
public ElasticsearchClient buildElasticsearchClient(Settings settings) {
8389
requireNonNull(settings, "settings is required");
8490

8591
settings.prefixSupplier(asList(ElasticsearchConfigurations.HOST, Configurations.HOST))
@@ -115,8 +121,7 @@ public ElasticsearchDocumentManagerFactory apply(Settings settings) {
115121
var transport = new RestClientTransport(httpClient, new JsonbJsonpMapper());
116122

117123
var elasticsearchClient = new ElasticsearchClient(transport);
118-
119-
return new ElasticsearchDocumentManagerFactory(elasticsearchClient);
124+
return elasticsearchClient;
120125
}
121126

122127
}

jnosql-elasticsearch/src/main/java/org/eclipse/jnosql/databases/elasticsearch/communication/ElasticsearchEntry.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ DocumentEntity toEntity() {
6060
List<Document> documents = map.keySet().stream()
6161
.map(k -> toDocument(k, map))
6262
.collect(Collectors.toList());
63-
DocumentEntity entity = DocumentEntity.of(collection, documents);
63+
DocumentEntity entity = DocumentEntity.of(collection);
64+
documents.forEach(d-> entity.add(d.name(),d.value()));
6465
entity.remove(EntityConverter.ID_FIELD);
6566
entity.remove(EntityConverter.ENTITY);
6667
entity.add(id);

jnosql-elasticsearch/src/main/java/org/eclipse/jnosql/databases/elasticsearch/communication/EntityConverter.java

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818

1919
import co.elastic.clients.elasticsearch.ElasticsearchClient;
2020
import co.elastic.clients.elasticsearch._types.SortOrder;
21-
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
22-
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
23-
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
2421
import co.elastic.clients.elasticsearch.core.SearchRequest;
2522
import co.elastic.clients.elasticsearch.core.SearchResponse;
2623
import org.eclipse.jnosql.communication.document.Document;
@@ -30,7 +27,6 @@
3027

3128
import java.io.IOException;
3229
import java.util.HashMap;
33-
import java.util.List;
3430
import java.util.Map;
3531
import java.util.function.Consumer;
3632
import java.util.stream.Stream;
@@ -59,18 +55,14 @@ static Map<String, Object> getMap(DocumentEntity entity) {
5955
}
6056

6157
static Stream<DocumentEntity> query(DocumentQuery query, ElasticsearchClient client, String index) {
62-
QueryConverterResult select = QueryConverter.select(query);
58+
QueryConverterResult select = QueryConverter.select(client, index, query);
6359

6460
try {
65-
Stream<DocumentEntity> idQueryStream = Stream.empty();
6661
Stream<DocumentEntity> statementQueryStream = Stream.empty();
67-
if (select.hasId()) {
68-
idQueryStream = executeId(client, index, select);
69-
}
7062
if (select.hasStatement()) {
7163
statementQueryStream = executeStatement(query, client, index, select);
7264
}
73-
return Stream.concat(idQueryStream, statementQueryStream).distinct();
65+
return statementQueryStream.distinct();
7466
} catch (IOException e) {
7567
throw new ElasticsearchException("An error to execute a query on elasticsearch", e);
7668
}
@@ -122,25 +114,6 @@ private static boolean isSudDocumentList(Object value) {
122114
allMatch(d -> d instanceof Iterable && isSudDocument(d));
123115
}
124116

125-
private static Stream<DocumentEntity> executeId(ElasticsearchClient client, String index,
126-
QueryConverterResult select) throws IOException {
127-
128-
List<Query> ids = select.getIds().stream()
129-
.map(id -> MatchQuery.of(m -> m
130-
.field(EntityConverter.ID_FIELD)
131-
.query(id))._toQuery()
132-
).collect(toList());
133-
134-
SearchRequest searchRequest = SearchRequest.of(sb -> sb
135-
.index(index)
136-
.query(BoolQuery.of(q -> q
137-
.should(ids))._toQuery()));
138-
SearchResponse<Map> responses = client.search(searchRequest, Map.class);
139-
140-
return getDocumentEntityStream(client, responses);
141-
142-
}
143-
144117
static Stream<DocumentEntity> getDocumentEntityStream(ElasticsearchClient client, SearchResponse<Map> responses) {
145118
return responses.hits().hits().stream()
146119
.map(hits -> ElasticsearchEntry.of(hits.id(), hits.source()))

jnosql-elasticsearch/src/main/java/org/eclipse/jnosql/databases/elasticsearch/communication/QueryConverter.java

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616
package org.eclipse.jnosql.databases.elasticsearch.communication;
1717

1818

19+
import co.elastic.clients.elasticsearch.ElasticsearchClient;
20+
import co.elastic.clients.elasticsearch._types.mapping.Property;
1921
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
22+
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
2023
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
2124
import co.elastic.clients.elasticsearch._types.query_dsl.QueryStringQuery;
2225
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
2326
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
27+
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
2428
import co.elastic.clients.json.JsonData;
2529
import org.eclipse.jnosql.communication.Condition;
2630
import org.eclipse.jnosql.communication.TypeReference;
@@ -29,15 +33,15 @@
2933
import org.eclipse.jnosql.communication.document.DocumentQuery;
3034
import org.eclipse.jnosql.communication.driver.ValueUtil;
3135

32-
import java.util.ArrayList;
36+
import java.io.IOException;
3337
import java.util.EnumSet;
3438
import java.util.List;
39+
import java.util.Map;
3540
import java.util.Objects;
3641
import java.util.Optional;
3742
import java.util.Set;
3843
import java.util.stream.Stream;
3944

40-
import static org.eclipse.jnosql.communication.Condition.EQUALS;
4145
import static org.eclipse.jnosql.communication.Condition.IN;
4246

4347
final 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

jnosql-elasticsearch/src/main/java/org/eclipse/jnosql/databases/elasticsearch/communication/QueryConverterResult.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,20 @@
1717

1818
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
1919

20-
import java.util.List;
21-
2220
class QueryConverterResult {
2321

2422
private final Query.Builder statement;
2523

26-
private final List<String> ids;
27-
28-
QueryConverterResult(Query.Builder statement, List<String> ids) {
24+
QueryConverterResult(Query.Builder statement) {
2925
this.statement = statement;
30-
this.ids = ids;
3126
}
3227

3328
Query.Builder getStatement() {
3429
return statement;
3530
}
3631

37-
List<String> getIds() {
38-
return ids;
39-
}
40-
41-
public boolean hasId() {
42-
return !ids.isEmpty();
43-
}
44-
4532
public boolean hasStatement() {
46-
return statement != null || ids.isEmpty();
33+
return statement != null;
4734
}
4835

4936
public boolean hasQuery() {

0 commit comments

Comments
 (0)