14
pom.xml
14
pom.xml
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
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();
|
||||
|
||||
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))
|
||||
)
|
||||
));
|
||||
}
|
||||
consulta.setDocumentos(documentos);
|
||||
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
|
||||
Referencia en una nueva incidencia
Block a user