Skip to content

Commit b0ced79

Browse files
committed
HSEARCH-3765 Add abstraction for extraction of IDs from Elasticearch documents
The same abstraction will be used by typing strategies (see next commits).
1 parent e97e0a4 commit b0ced79

16 files changed

+115
-79
lines changed

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/index/impl/IndexManagerBackendContext.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.hibernate.search.backend.elasticsearch.link.impl.ElasticsearchLink;
1313
import org.hibernate.search.backend.elasticsearch.scope.model.impl.ElasticsearchScopeModel;
1414
import org.hibernate.search.backend.elasticsearch.search.impl.ElasticsearchSearchContext;
15-
import org.hibernate.search.backend.elasticsearch.search.projection.impl.DocumentReferenceExtractorHelper;
15+
import org.hibernate.search.backend.elasticsearch.search.projection.impl.DocumentReferenceExtractionHelper;
1616
import org.hibernate.search.backend.elasticsearch.search.projection.impl.ElasticsearchSearchProjection;
1717
import org.hibernate.search.backend.elasticsearch.search.projection.impl.SearchProjectionBackendContext;
1818
import org.hibernate.search.backend.elasticsearch.search.query.impl.ElasticsearchSearchQueryBuilder;
@@ -51,7 +51,7 @@ public class IndexManagerBackendContext implements SearchBackendContext, WorkExe
5151
private final ElasticsearchWorkOrchestratorProvider orchestratorProvider;
5252
private final ElasticsearchWorkOrchestrator queryOrchestrator;
5353

54-
private final DocumentReferenceExtractorHelper documentReferenceExtractorHelper;
54+
private final DocumentReferenceExtractionHelper documentReferenceExtractionHelper;
5555
private final SearchProjectionBackendContext searchProjectionBackendContext;
5656

5757
public IndexManagerBackendContext(EventContext eventContext, ElasticsearchLink link, Gson userFacingGson,
@@ -66,10 +66,10 @@ public IndexManagerBackendContext(EventContext eventContext, ElasticsearchLink l
6666
this.orchestratorProvider = orchestratorProvider;
6767
this.queryOrchestrator = queryOrchestrator;
6868

69-
this.documentReferenceExtractorHelper =
70-
new DocumentReferenceExtractorHelper( indexNameConverter, multiTenancyStrategy );
69+
this.documentReferenceExtractionHelper =
70+
new DocumentReferenceExtractionHelper( indexNameConverter, multiTenancyStrategy.getIdProjectionExtractionHelper() );
7171
this.searchProjectionBackendContext = new SearchProjectionBackendContext(
72-
documentReferenceExtractorHelper
72+
documentReferenceExtractionHelper
7373
);
7474
}
7575

@@ -118,8 +118,8 @@ public IndexWorkspace createWorkspace(ElasticsearchWorkOrchestrator orchestrator
118118
}
119119

120120
@Override
121-
public DocumentReferenceExtractorHelper getDocumentReferenceExtractorHelper() {
122-
return documentReferenceExtractorHelper;
121+
public DocumentReferenceExtractionHelper getDocumentReferenceExtractionHelper() {
122+
return documentReferenceExtractionHelper;
123123
}
124124

125125
@Override

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/multitenancy/impl/DiscriminatorMultiTenancyStrategy.java

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonObjectAccessor;
1919
import org.hibernate.search.backend.elasticsearch.document.impl.DocumentMetadataContributor;
2020
import org.hibernate.search.backend.elasticsearch.logging.impl.Log;
21+
import org.hibernate.search.backend.elasticsearch.search.projection.impl.ProjectionExtractionHelper;
2122
import org.hibernate.search.backend.elasticsearch.util.impl.ElasticsearchFields;
2223
import org.hibernate.search.util.common.reporting.EventContext;
2324
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
@@ -34,17 +35,12 @@ public class DiscriminatorMultiTenancyStrategy implements MultiTenancyStrategy {
3435

3536
private static final String ESCAPED_UNDERSCORE = "__";
3637

37-
private static final JsonArrayAccessor DOCVALUE_FIELDS_ACCESSOR = JsonAccessor.root().property( "docvalue_fields" ).asArray();
38-
39-
private static final JsonAccessor<String> HIT_ID_ACCESSOR = JsonAccessor.root().property( "fields" ).asObject()
40-
.property( ElasticsearchFields.idFieldName() ).asArray()
41-
.element( 0 ).asString();
42-
43-
private static final JsonElement ID_FIELD_NAME_JSON = new JsonPrimitive( ElasticsearchFields.idFieldName() );
44-
4538
private final DiscriminatorMultiTenancyDocumentMetadataContributor documentMetadataContributor =
4639
new DiscriminatorMultiTenancyDocumentMetadataContributor();
4740

41+
private final DiscriminatorMultiTenancyIdProjectionExtractionHelper idProjectionExtractionHelper =
42+
new DiscriminatorMultiTenancyIdProjectionExtractionHelper();
43+
4844
@Override
4945
public boolean isMultiTenancySupported() {
5046
return true;
@@ -94,13 +90,8 @@ public JsonObject decorateJsonQuery(JsonObject originalJsonQuery, String tenantI
9490
}
9591

9692
@Override
97-
public void contributeToSearchRequest(JsonObject requestBody) {
98-
DOCVALUE_FIELDS_ACCESSOR.addElementIfAbsent( requestBody, ID_FIELD_NAME_JSON );
99-
}
100-
101-
@Override
102-
public String extractTenantScopedDocumentId(JsonObject hit) {
103-
return HIT_ID_ACCESSOR.get( hit ).orElseThrow( log::elasticsearchResponseMissingData );
93+
public DiscriminatorMultiTenancyIdProjectionExtractionHelper getIdProjectionExtractionHelper() {
94+
return idProjectionExtractionHelper;
10495
}
10596

10697
@Override
@@ -122,4 +113,27 @@ public void contribute(JsonObject document, String tenantId, String id) {
122113
ID_ACCESSOR.set( document, id );
123114
}
124115
}
116+
117+
private static final class DiscriminatorMultiTenancyIdProjectionExtractionHelper implements ProjectionExtractionHelper<String> {
118+
private static final JsonArrayAccessor DOCVALUE_FIELDS_ACCESSOR =
119+
JsonAccessor.root().property( "docvalue_fields" ).asArray();
120+
121+
private static final JsonAccessor<String> HIT_ID_ACCESSOR =
122+
JsonAccessor.root().property( "fields" ).asObject()
123+
.property( ElasticsearchFields.idFieldName() ).asArray()
124+
.element( 0 ).asString();
125+
126+
private static final JsonElement ID_FIELD_NAME_JSON =
127+
new JsonPrimitive( ElasticsearchFields.idFieldName() );
128+
129+
@Override
130+
public void request(JsonObject requestBody) {
131+
DOCVALUE_FIELDS_ACCESSOR.addElementIfAbsent( requestBody, ID_FIELD_NAME_JSON );
132+
}
133+
134+
@Override
135+
public String extract(JsonObject hit) {
136+
return HIT_ID_ACCESSOR.get( hit ).orElseThrow( log::elasticsearchResponseMissingData );
137+
}
138+
}
125139
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/multitenancy/impl/MultiTenancyStrategy.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.hibernate.search.backend.elasticsearch.document.impl.DocumentMetadataContributor;
1212
import org.hibernate.search.backend.elasticsearch.document.model.esnative.impl.RootTypeMapping;
13+
import org.hibernate.search.backend.elasticsearch.search.projection.impl.ProjectionExtractionHelper;
1314
import org.hibernate.search.util.common.reporting.EventContext;
1415

1516
import com.google.gson.JsonObject;
@@ -59,19 +60,9 @@ public interface MultiTenancyStrategy {
5960
JsonObject decorateJsonQuery(JsonObject originalJsonQuery, String tenantId);
6061

6162
/**
62-
* Contributes additional elements to the Elasticsearch search request.
63-
*
64-
* @param requestBody The body of the request.
65-
*/
66-
void contributeToSearchRequest(JsonObject requestBody);
67-
68-
/**
69-
* Extracts the tenant-scoped document id from an Elasticsearch hit.
70-
*
71-
* @param hit The Elasticsearch hit.
72-
* @return The tenant scoped document id.
63+
* @return A helper for projections that need to extract the document id from search hits.
7364
*/
74-
String extractTenantScopedDocumentId(JsonObject hit);
65+
ProjectionExtractionHelper<String> getIdProjectionExtractionHelper();
7566

7667
/**
7768
* Check that the tenant id value is consistent with the strategy.

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/multitenancy/impl/NoMultiTenancyStrategy.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
1414
import org.hibernate.search.backend.elasticsearch.document.impl.DocumentMetadataContributor;
1515
import org.hibernate.search.backend.elasticsearch.logging.impl.Log;
16+
import org.hibernate.search.backend.elasticsearch.search.projection.impl.ProjectionExtractionHelper;
1617
import org.hibernate.search.util.common.reporting.EventContext;
1718
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
1819

@@ -22,7 +23,8 @@ public class NoMultiTenancyStrategy implements MultiTenancyStrategy {
2223

2324
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );
2425

25-
private static final JsonAccessor<String> HIT_ID_ACCESSOR = JsonAccessor.root().property( "_id" ).asString();
26+
private final NoMultiTenancyIdProjectionExtractionHelper idProjectionExtractionHelper =
27+
new NoMultiTenancyIdProjectionExtractionHelper();
2628

2729
@Override
2830
public boolean isMultiTenancySupported() {
@@ -51,13 +53,8 @@ public JsonObject decorateJsonQuery(JsonObject originalJsonQuery, String tenantI
5153
}
5254

5355
@Override
54-
public void contributeToSearchRequest(JsonObject requestBody) {
55-
// No need to request any additional information, Elasticsearch metadata is enough
56-
}
57-
58-
@Override
59-
public String extractTenantScopedDocumentId(JsonObject hit) {
60-
return HIT_ID_ACCESSOR.get( hit ).orElseThrow( log::elasticsearchResponseMissingData );
56+
public NoMultiTenancyIdProjectionExtractionHelper getIdProjectionExtractionHelper() {
57+
return idProjectionExtractionHelper;
6158
}
6259

6360
@Override
@@ -66,4 +63,19 @@ public void checkTenantId(String tenantId, EventContext backendContext) {
6663
throw log.tenantIdProvidedButMultiTenancyDisabled( tenantId, backendContext );
6764
}
6865
}
66+
67+
private static final class NoMultiTenancyIdProjectionExtractionHelper implements ProjectionExtractionHelper<String> {
68+
private static final JsonAccessor<String> HIT_ID_ACCESSOR =
69+
JsonAccessor.root().property( "_id" ).asString();
70+
71+
@Override
72+
public void request(JsonObject requestBody) {
73+
// No need to request any additional information, Elasticsearch metadata is enough
74+
}
75+
76+
@Override
77+
public String extract(JsonObject hit) {
78+
return HIT_ID_ACCESSOR.get( hit ).orElseThrow( log::elasticsearchResponseMissingData );
79+
}
80+
}
6981
}
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,38 @@
1111

1212
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
1313
import org.hibernate.search.backend.elasticsearch.logging.impl.Log;
14-
import org.hibernate.search.backend.elasticsearch.multitenancy.impl.MultiTenancyStrategy;
1514
import org.hibernate.search.backend.elasticsearch.search.impl.ElasticsearchDocumentReference;
1615
import org.hibernate.search.engine.backend.common.DocumentReference;
1716
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
1817

1918
import com.google.gson.JsonObject;
2019

21-
public class DocumentReferenceExtractorHelper {
20+
public final class DocumentReferenceExtractionHelper implements ProjectionExtractionHelper<DocumentReference> {
2221
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );
2322

2423
private static final JsonAccessor<String> HIT_INDEX_NAME_ACCESSOR = JsonAccessor.root().property( "_index" ).asString();
2524

2625
private final Function<String, String> indexNameConverter;
27-
private final MultiTenancyStrategy multiTenancyStrategy;
26+
private final ProjectionExtractionHelper<String> idHelper;
2827

29-
public DocumentReferenceExtractorHelper(Function<String, String> indexNameConverter,
30-
MultiTenancyStrategy multiTenancyStrategy) {
28+
public DocumentReferenceExtractionHelper(
29+
Function<String, String> indexNameConverter,
30+
ProjectionExtractionHelper<String> idHelper) {
3131
this.indexNameConverter = indexNameConverter;
32-
this.multiTenancyStrategy = multiTenancyStrategy;
32+
this.idHelper = idHelper;
3333
}
3434

35-
public void requestDocumentReference(JsonObject requestBody) {
36-
multiTenancyStrategy.contributeToSearchRequest( requestBody );
35+
@Override
36+
public void request(JsonObject requestBody) {
37+
idHelper.request( requestBody );
3738
}
3839

39-
public DocumentReference extractDocumentReference(JsonObject hit) {
40+
@Override
41+
public DocumentReference extract(JsonObject hit) {
4042
String indexName = HIT_INDEX_NAME_ACCESSOR.get( hit )
4143
.map( indexNameConverter )
4244
.orElseThrow( log::elasticsearchResponseMissingData );
43-
String id = multiTenancyStrategy.extractTenantScopedDocumentId( hit );
45+
String id = idHelper.extract( hit );
4446
return new ElasticsearchDocumentReference( indexName, id );
4547
}
4648
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/impl/ElasticsearchDocumentReferenceProjection.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@ class ElasticsearchDocumentReferenceProjection
1818
implements ElasticsearchSearchProjection<DocumentReference, DocumentReference> {
1919

2020
private final Set<String> indexNames;
21-
private final DocumentReferenceExtractorHelper helper;
21+
private final DocumentReferenceExtractionHelper helper;
2222

23-
ElasticsearchDocumentReferenceProjection(Set<String> indexNames, DocumentReferenceExtractorHelper helper) {
23+
ElasticsearchDocumentReferenceProjection(Set<String> indexNames, DocumentReferenceExtractionHelper helper) {
2424
this.indexNames = indexNames;
2525
this.helper = helper;
2626
}
2727

2828
@Override
2929
public void request(JsonObject requestBody, SearchProjectionRequestContext context) {
30-
helper.requestDocumentReference( requestBody );
30+
helper.request( requestBody );
3131
}
3232

3333
@Override
3434
public DocumentReference extract(ProjectionHitMapper<?, ?> projectionHitMapper, JsonObject hit,
3535
SearchProjectionExtractContext context) {
36-
return helper.extractDocumentReference( hit );
36+
return helper.extract( hit );
3737
}
3838

3939
@Override

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/impl/ElasticsearchDocumentReferenceProjectionBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ElasticsearchDocumentReferenceProjectionBuilder implements DocumentReferen
1717

1818
private final ElasticsearchDocumentReferenceProjection projection;
1919

20-
ElasticsearchDocumentReferenceProjectionBuilder(Set<String> indexNames, DocumentReferenceExtractorHelper helper) {
20+
ElasticsearchDocumentReferenceProjectionBuilder(Set<String> indexNames, DocumentReferenceExtractionHelper helper) {
2121
this.projection = new ElasticsearchDocumentReferenceProjection( indexNames, helper );
2222
}
2323

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/impl/ElasticsearchEntityProjection.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@
1616
public class ElasticsearchEntityProjection<E> implements ElasticsearchSearchProjection<Object, E> {
1717

1818
private final Set<String> indexNames;
19-
private final DocumentReferenceExtractorHelper helper;
19+
private final DocumentReferenceExtractionHelper helper;
2020

21-
public ElasticsearchEntityProjection(Set<String> indexNames, DocumentReferenceExtractorHelper helper) {
21+
public ElasticsearchEntityProjection(Set<String> indexNames, DocumentReferenceExtractionHelper helper) {
2222
this.indexNames = indexNames;
2323
this.helper = helper;
2424
}
2525

2626
@Override
2727
public void request(JsonObject requestBody, SearchProjectionRequestContext context) {
28-
helper.requestDocumentReference( requestBody );
28+
helper.request( requestBody );
2929
}
3030

3131
@Override
3232
public Object extract(ProjectionHitMapper<?, ?> projectionHitMapper, JsonObject hit,
3333
SearchProjectionExtractContext context) {
34-
return projectionHitMapper.planLoading( helper.extractDocumentReference( hit ) );
34+
return projectionHitMapper.planLoading( helper.extract( hit ) );
3535
}
3636

3737
@SuppressWarnings("unchecked")

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/impl/ElasticsearchEntityProjectionBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ElasticsearchEntityProjectionBuilder<E> implements EntityProjectionBuilder
1616

1717
private final ElasticsearchEntityProjection<E> projection;
1818

19-
ElasticsearchEntityProjectionBuilder(Set<String> indexNames, DocumentReferenceExtractorHelper helper) {
19+
ElasticsearchEntityProjectionBuilder(Set<String> indexNames, DocumentReferenceExtractionHelper helper) {
2020
this.projection = new ElasticsearchEntityProjection<>( indexNames, helper );
2121
}
2222

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/impl/ElasticsearchEntityReferenceProjection.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@
1616
public class ElasticsearchEntityReferenceProjection<R> implements ElasticsearchSearchProjection<R, R> {
1717

1818
private final Set<String> indexNames;
19-
private final DocumentReferenceExtractorHelper helper;
19+
private final DocumentReferenceExtractionHelper helper;
2020

21-
public ElasticsearchEntityReferenceProjection(Set<String> indexNames, DocumentReferenceExtractorHelper helper) {
21+
public ElasticsearchEntityReferenceProjection(Set<String> indexNames, DocumentReferenceExtractionHelper helper) {
2222
this.indexNames = indexNames;
2323
this.helper = helper;
2424
}
2525

2626
@Override
2727
public void request(JsonObject requestBody, SearchProjectionRequestContext context) {
28-
helper.requestDocumentReference( requestBody );
28+
helper.request( requestBody );
2929
}
3030

3131
@SuppressWarnings("unchecked")
3232
@Override
3333
public R extract(ProjectionHitMapper<?, ?> projectionHitMapper, JsonObject hit,
3434
SearchProjectionExtractContext context) {
35-
return (R) projectionHitMapper.convertReference( helper.extractDocumentReference( hit ) );
35+
return (R) projectionHitMapper.convertReference( helper.extract( hit ) );
3636
}
3737

3838
@Override

0 commit comments

Comments
 (0)