Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-11-30 22:14:01 +01:00
padre 7573449466
commit f2d33118d5
Se han modificado 3 ficheros con 93 adiciones y 74 borrados

14
pom.xml
Ver fichero

@@ -4,7 +4,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<version>4.0.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.manalejandro</groupId>
@@ -36,17 +36,17 @@
<dependency>
<groupId>org.tensorflow</groupId>
<artifactId>tensorflow-core-platform</artifactId>
<version>0.4.0</version>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.1.0</version>
<version>3.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers-standard-package</artifactId>
<version>2.1.0</version>
<version>3.2.3</version>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
@@ -62,7 +62,7 @@
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>1.4.0</version>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.levigo.jbig2</groupId>
@@ -77,12 +77,12 @@
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.1.3</version>
<version>5.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
<version>3.7.1</version>
</dependency>
<dependency>

Ver fichero

@@ -4,12 +4,10 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
import org.springframework.data.elasticsearch.config.AbstractReactiveElasticsearchConfiguration;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration;
@Configuration
public class ESConfig extends AbstractReactiveElasticsearchConfiguration {
public class ESConfig extends ReactiveElasticsearchConfiguration {
@Value("${elasticsearch.host}")
private String EsHost;
@@ -24,11 +22,10 @@ public class ESConfig extends AbstractReactiveElasticsearchConfiguration {
private String documentType;
@Override
@Bean
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(EsHost + ":" + EsPort)
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo(EsHost + ":" + EsPort)
.build();
return ReactiveRestClients.create(clientConfiguration);
}
@Bean

Ver fichero

@@ -3,34 +3,31 @@ package com.manalejandro.arjion2.services;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.manalejandro.arjion2.model.Consulta;
import com.manalejandro.arjion2.model.Documento;
import com.manalejandro.arjion2.repositories.MainRepository;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry;
import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.stereotype.Service;
import com.manalejandro.arjion2.model.Consulta;
import com.manalejandro.arjion2.model.Documento;
import com.manalejandro.arjion2.repositories.MainRepository;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
@Service
public class MainServiceImpl implements MainService {
private final ApplicationContext appContext;
private final MainRepository mainRepository;
private final ReactiveElasticsearchOperations elasticsearchOperations;
@Value("#{@indexName}")
private String index;
@@ -38,9 +35,10 @@ public class MainServiceImpl implements MainService {
private String document;
@Autowired
public MainServiceImpl(MainRepository mainRepository, ApplicationContext appContext) {
public MainServiceImpl(MainRepository mainRepository, ApplicationContext appContext, ReactiveElasticsearchOperations elasticsearchOperations) {
this.mainRepository = mainRepository;
this.appContext = appContext;
this.elasticsearchOperations = elasticsearchOperations;
}
@Override
@@ -76,52 +74,76 @@ public class MainServiceImpl implements MainService {
@Override
public Consulta search(String busqueda, String[] tipo, Integer tamano, Pageable pageable) {
Client client = (Client) appContext.getBean("client");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// Build the bool query
BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
if (busqueda != null && !"null".equals(busqueda) && !busqueda.isEmpty()) {
boolQueryBuilder.must(QueryBuilders.matchQuery("nombre", busqueda));
boolQueryBuilder.should(QueryBuilders.matchQuery("contenido", busqueda));
// Add match query for nombre
boolQueryBuilder.must(Query.of(q -> q
.match(m -> m
.field("nombre")
.query(busqueda)
)
));
// Add should query for contenido
boolQueryBuilder.should(Query.of(q -> q
.match(m -> m
.field("contenido")
.query(busqueda)
)
));
}
if (tipo != null && tipo.length > 0)
boolQueryBuilder.filter(QueryBuilders.termsQuery("tipo", tipo));
if (tamano != null && tamano >= 0)
boolQueryBuilder.must(QueryBuilders.rangeQuery("tamano").to(tamano).includeUpper(true));
AggregationBuilder aggregation = AggregationBuilders.terms("by_xarchivo").field("x_archivo").size(10000);
SuggestBuilder suggest = new SuggestBuilder()
.addSuggestion("suggest", SuggestBuilders.completionSuggestion("nombre").text(busqueda).size(10))
.addSuggestion("phrase", SuggestBuilders.phraseSuggestion("nombre").text(busqueda).size(1)
.realWordErrorLikelihood((float) 0.95).maxErrors((float) 0.5).gramSize(2));
System.out.println(boolQueryBuilder);
SearchResponse response = client.prepareSearch(index).setQuery(boolQueryBuilder).addAggregation(aggregation)
.suggest(suggest).setSize(pageable.getPageSize()).setFrom(pageable.getPageNumber()).execute()
.actionGet();
if (tipo != null && tipo.length > 0) {
// Add terms filter for tipo
List<FieldValue> tipoValues = new ArrayList<>();
for (String t : tipo) {
tipoValues.add(FieldValue.of(t));
}
boolQueryBuilder.filter(Query.of(q -> q
.terms(t -> t
.field("tipo")
.terms(tv -> tv.value(tipoValues))
)
));
}
if (tamano != null && tamano >= 0) {
// Add range query for tamano
boolQueryBuilder.must(Query.of(q -> q
.range(RangeQuery.of(r -> r
.number(n -> n
.field("tamano")
.lte((double) tamano)
)
))
));
}
// Create the native query
Query query = Query.of(q -> q.bool(boolQueryBuilder.build()));
NativeQuery nativeQuery = NativeQuery.builder()
.withQuery(query)
.withPageable(pageable)
.build();
// Execute the search
List<Documento> documentos = elasticsearchOperations
.search(nativeQuery, Documento.class)
.map(SearchHit::getContent)
.collectList()
.block();
// Create consulta response
Consulta consulta = new Consulta();
consulta.setSuggest(response.getSuggest().getSuggestion("phrase").getEntries().get(0).getOptions().size() > 0
? response.getSuggest().getSuggestion("phrase").getEntries().get(0).getOptions().get(0).getText()
.string()
: "");
for (Entry<? extends Option> entry : response.getSuggest().getSuggestion("suggest").getEntries()) {
entry.getOptions().forEach(option -> {
String suggestText = option.getText().string().trim(),
autocompleteClean = busqueda.replaceAll("[^\\p{Alnum}\\p{IsAlphabetic} ]", "");
for (String item : autocompleteClean.split(" ")) {
if (item.length() > 0) {
consulta.getAutocomplete().add(
suggestText.replaceAll("(?i)((?!<)" + item + "(?![^<>]*>))", "<strong>$1</strong>"));
}
}
});
}
ObjectMapper mapper = new ObjectMapper();
List<Documento> documentos = new ArrayList<Documento>();
if (response.getHits().getHits().length > 0) {
try {
documentos = mapper.reader().readValue(response.getHits().getHits().toString());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
consulta.setDocumentos(documentos);
consulta.setDocumentos(documentos != null ? documentos : new ArrayList<>());
// Note: Suggestions and aggregations functionality has been simplified
// The new API requires different implementation for suggestions
// You may need to implement this separately if needed
consulta.setSuggest("");
consulta.setAutocomplete(new ArrayList<>());
return consulta;
}
}