Implementando searchLikeBy en MongoDB con Jmoordbcore 1/3
Tags: jmoordbcore, mongodb, jakartaee
Published: 2023-11-23 21:00:57

En muchas ocasiones necesitamos realizar consultas mediante expresiones regulares que se unen con otras condiciones de búsqueda en la que se necesita utilizar paginación y ordenación.  
Vídeo de muestra [Búsquedas con expresiones regulares en MongoDB mediante Jmoordbcore](https://youtu.be/_cI_6IO-vrA)
En JmoordbCore es posible utilizar la anotación @SearchByLike, para generar consultas utilizando expresiones regulares combinadas. Por ejemplo:

```java
@SearchLikeBy(caseSensitive = CaseSensitive.NO, typeOrder = TypeOrder.ASC, likeByType = LikeByType.ANYWHERE)
    public List<Tarjeta> searchLikeByTarjeta(String tarjeta, Search search);
```

En este ejemplo utilizaremos un Microservicio que utiliza [https://microprofile.io/](https://microprofile.io/) con una base de datos [MongoDB](https://www.mongodb.com/es), que se comunica mediante Jmoordbcore.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b79gu4e64tpoe6scc5w.png)


Se cuenta con documentos que almacenan información sobre tarjetas con atributos similares a estos

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8bb3y7smbmwp9l4wiyb3.png)

Las interfaces de usuario se desarrollan utilizando [Jakarta Faces](https://jakarta.ee/specifications/faces/) con [Primefaces](https://www.primefaces.org/), como se muestra en la siguiente figura:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kd5b8n6c7cah4m11nofl.png)

Pasos:
1. Cree un proyecto Jakarta EE con Payara Starter [https://start.payara.fish/](https://start.payara.fish/)
2. Agregue la dependencia de jmoordbcore

```xml
  <version.jmoordbcore>1.0.0.b-7</version.jmoordbcore>

 <dependency>
     <groupId>com.github.avbravo</groupId>
     <artifactId>jmoordb-core</artifactId>
     <version>${version.jmoordbcore}</version>
 </dependency>

 <repositories>
   <repository>
      <id>jitpack.io</id>
     <url>https://jitpack.io</url>
  </repository>
 </repositories>
```

3. Agrega propiedades de conexión a la base de datos en el archivo microprofile-config.properties

```xml

mongodb.uri=mongodb://localhost:27017
#-- Database de configuración
mongodb.jmoordb= configurationjmoordbdb

#-- Database History
mongodb.databasehistory=historydb

#-- Database
mongodb.database=accreditation
mongodb.database1=sft
mongodb.database2=practicadb

```
4. Defina la entidad Tarjeta que representa un documento de la colección

```java
@Entity
public class Tarjeta {

    @Id(autogeneratedActive = AutogeneratedActive.ON)
    private Long idtarjeta;
    @Column
    private String tarjeta;
    @Column
    private String descripcion;

    @ViewReferenced(from = "user", localField = "iduser")
    List<UserView> userView;

    @Column
    private Date fechainicial;
    @Column
    private Date fechafinal;
    @Referenced(from = "icono", localField = "idicono", commentary = "Esta asociado a la prioridad")
    private Icono icono;
    @Referenced(from = "tipotarjeta", localField = "idtipotarjeta", commentary = "Ayuda para la implementación de Deep Learning")
    private Tipotarjeta tipotarjeta;

    @Column
    private Long idsprint;

    @Column
    private Long idproyecto;

    @Column
    private Boolean backlog;

    @Column(commentary = "alta,baja,media")
    private String prioridad;

    @Column
    private String estimacion;

    @Column(commentary = "pendiente,progreso,finalizado")
    private String columna;
    @Column
    private Boolean active;

    @Embedded
    List<Tarea> tarea;

    @Embedded
    List<Comentario> comentario;

    @Embedded
    List<Etiqueta> etiqueta;

    @Embedded
    List<Archivo> archivo;

    @Embedded
    List<Impedimento> impedimento;

    @Column(commentary = "true cuando la crea un colaborador que no pertenece al proyecto y es un proyecto publico")
    private Boolean foreaneo;

    @Embedded
    List<ActionHistory> actionHistory;

    public Tarjeta() {
    }

...
}
```

5. Defina el repositorio TarjetaRepository.java, con métodos para contar los documentos y realizar búsquedas combinando expresiones regulares con otros filtros.

```java
@Repository(database = "{mongodb.database1}", entity = Tarjeta.class)
public interface TarjetaRepository extends CrudRepository<Tarjeta, Long> {

 @SearchCountLikeBy(caseSensitive = CaseSensitive.NO, likeByType = LikeByType.ANYWHERE)
    public Long searchCountLikeByTarjeta(String tarjeta, Search search);
    
    @SearchCountLikeBy(caseSensitive = CaseSensitive.NO, likeByType = LikeByType.ANYWHERE)
    public Long searchCountLikeByDescripcion(String descripcion, Search search);

 @SearchLikeBy(caseSensitive = CaseSensitive.NO, typeOrder = TypeOrder.ASC, likeByType = LikeByType.ANYWHERE)
    public List<Tarjeta> searchLikeByTarjeta(String tarjeta, Search search);

    @SearchLikeBy(caseSensitive = CaseSensitive.NO, typeOrder = TypeOrder.ASC, likeByType = LikeByType.ANYWHERE)
    public List<Tarjeta> searchLikeByDescripcion(String descripcion, Search search);

}
```

6. Cree una clase controladora llamada TarjetaController.java

```java
@Path("tarjeta")
@Tag(name = "Información del tarjeta", description = "End-point para entidad Tarjeta")
@RolesAllowed({"admin"})
public class TarjetaController {

    
@GET
@Path("searchcountlikebytarjeta")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public  Long searchCountLikeByTarjeta(@QueryParam("tarjeta") String tarjeta, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
      Long result = 0L;
        try {
            Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
           result= tarjetaRepository.searchCountLikeByTarjeta(tarjeta, search);
        } catch (Exception e) {
            MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }
        return result;
    }

    
@GET
@Path("searchcountlikebydescripcion")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public  Long searchCountLikeByDescripcion(@QueryParam("descripcion") String descripcion, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
       Long result = 0L;
        try {
            Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
           result= tarjetaRepository.searchCountLikeByDescripcion(descripcion, search);
        } catch (Exception e) {
            MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }
        return result;
    }

@GET
@Path("likebytarjetasearch")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Tarjeta> searchLikeByTarjeta(@QueryParam("tarjeta") String tarjeta, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
        List<Tarjeta> suggestions = new ArrayList<>();
        try {
            Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
            suggestions = tarjetaRepository.searchLikeByTarjeta(tarjeta, search);
        } catch (Exception e) {
            MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }
        return suggestions;
    }


@GET
@Path("likebydescripcionsearch")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Tarjeta> searchLikeByDescripcion(@QueryParam("descripcion") String descripcion, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
        List<Tarjeta> suggestions = new ArrayList<>();
        try {
            Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
            suggestions = tarjetaRepository.searchLikeByDescripcion(descripcion, search);
        } catch (Exception e) {
            MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }
        return suggestions;
    }
}
```

**Creando el Cliente**
Pasos:
1. Cree un proyecto nuevo con Cree un proyecto Jakarta EE con Payara Starter [https://start.payara.fish/](https://start.payara.fish/)

2. Agregue al archivo microprofile-config.properties restclient

```java
com.sft.restclient.TarjetaRestClient/mp-rest/url=http://localhost:9002/accreditation/api/
```
3. Cree la entidad tarjeta que definió en el microservicio.

4. Cree las interfaces para el endpoint tarjeta

```java
@RegisterRestClient()
@Path("/tarjeta")

public interface TarjetaRestClient {
@GET
@Path("likebytarjetasearch")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
List<Tarjeta> searchLikeByTarjeta(@QueryParam("tarjeta") String tarjeta, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size);
    
@GET
@Path("likebydescripcionsearch")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
List<Tarjeta> searchLikeByDescripcion(@QueryParam("descripcion") String descripcion, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size);
    
    
@GET
@Path("searchcountlikebytarjeta")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public  Long searchCountLikeByTarjeta(@QueryParam("tarjeta") String tarjeta, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size);

   
@GET
@Path("searchcountlikebydescripcion")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public  Long searchCountLikeByDescripcion(@QueryParam("descripcion") String descripcion, @QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size);

```

5. Cree la interface TarjetaServices

```java
public interface TarjetaServices {

public List<Tarjeta> searchLikeByTarjeta(String tarjeta, Bson filter, Document sort, Integer page, Integer size);
    public Long searchCountLikeByTarjeta(String tarjeta, Bson filter, Document sort, Integer page, Integer size);
    
    public List<Tarjeta> searchLikeByDescripcion(String descripcion, Bson filter, Document sort, Integer page, Integer size);
        public Long searchCountLikeByDescripcion(String descripcion, Bson filter, Document sort, Integer page, Integer size);
  
}


```
6. Cree la implementación

```java
@ApplicationScoped
public class TarjetaServicesImpl implements TarjetaServices {


@Inject
TarjetaRestClient tarjetaRestClient;



    @Override
    public List<Tarjeta> searchLikeByTarjeta(String tarjeta, Bson filter, Document sort, Integer page, Integer size) {
        List<Tarjeta> tarjetaList = new ArrayList<>();
        try {
            tarjetaList = tarjetaRestClient.searchLikeByTarjeta(tarjeta,
                    EncodeUtil.encodeBson(filter),
                    EncodeUtil.encodeBson(sort),
                    page, size);
        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return tarjetaList;
    }

    


    @Override
    public Long searchCountLikeByTarjeta(String tarjeta, Bson filter, Document sort, Integer page, Integer size) {
        Long result = 0L;
        try {
            result = tarjetaRestClient.searchCountLikeByTarjeta(tarjeta,
                    EncodeUtil.encodeBson(filter),
                    EncodeUtil.encodeBson(sort),
                    page, size);
        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return result;
    }


    @Override
    public List<Tarjeta> searchLikeByDescripcion(String descripcion, Bson filter, Document sort, Integer page, Integer size) {
        List<Tarjeta> tarjetaList = new ArrayList<>();
        try {
            tarjetaList = tarjetaRestClient.searchLikeByDescripcion(descripcion,
                    EncodeUtil.encodeBson(filter),
                    EncodeUtil.encodeBson(sort),
                    page, size);
        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return tarjetaList;
    }

    
    
    @Override
    public Long searchCountLikeByDescripcion(String descripcion, Bson filter, Document sort, Integer page, Integer size) {
        Long result = 0L;
        try {
            result = tarjetaRestClient.searchCountLikeByDescripcion(descripcion,
                    EncodeUtil.encodeBson(filter),
                    EncodeUtil.encodeBson(sort),
                    page, size);
        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return result;
    }


}

```
6. Diseñe la interface de usuario con Jakarta Server Faces y Primefaces para realizar búsquedas, quedando de la siguiente manera:

![Interface de usuario](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4qziwwdj7zxnbyj751o.png)

Entre los elementos usados se encuentran:

- inputText

- selectOneMenu

- dataTable

Se usara un datable, con columnas y componentes que no se muestran completamente en la siguiente sección:

```
<p:dataTable var="item" value="#{buscadorTarjetasFaces.tarjetaLazyDataModel}"
 binding="#{buscadorTarjetasFaces.dataTable}"
 id="dataTable"
widgetVar="widgetVardataTable"
lazy="true"
paginator="true"
rows="#{buscadorTarjetasFaces.rowPageSmall.get()}"                                           paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
paginatorPosition="both"
reflow="true"
rowKey="#{item.idtarjeta}"
selection="#{buscadorTarjetasFaces.tarjetaSelected}"
rowSelectMode="add">
<p:column class="column2">
 <p:rowToggler/>
</p:column>
 <p:column class="column8" headerText="#{msg['field.idtarjeta']}">
 <p:outputLabel value="#{item.idtarjeta}"/>
</p:column>
...
```

![Formulario de búsquedas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xnyx0ava3lo8l3bl9mo.png)

7. Cree la clase BuscadorTarjetasFaces

```java
@Named
@ViewScoped
@Data
public class BuscadorTarjetasFaces implements Serializable, JmoordbCoreXHTMLUtil, IPaginator, SprintFacesServices {


@Inject
TarjetaServices tarjetaServices;


```
En el método init() se realizara la administración de la paginación insertando el siguiente codigo

```java
this.tarjetaLazyDataModel = new LazyDataModel<Tarjeta>() {
    @Override
    public List<Tarjeta> load(int offset, int pageSize, Map<String, SortMeta> sortBy, Map<String, FilterMeta> filterBy) {

        if (textDescripcionToSearch == null || textDescripcionToSearch.equals("")) {
            totalRecords = tarjetaServices.searchCountLikeByTarjeta(textToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get()).intValue();
        } else {
            if ((textToSearch == null || textToSearch.equals("")) && (textDescripcionToSearch != null || !textDescripcionToSearch.equals(""))) {

                totalRecords = tarjetaServices.searchCountLikeByDescripcion(textDescripcionToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get()).intValue();
            } else {

                totalRecords = tarjetaServices.searchCountLikeByTarjeta(textToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get()).intValue();
            }
        }


        List<Paginator> list = new ArrayList<>();
        if (!isRowPageSmall) {

            /**
             * Utiliza rowPage
             */
            list = processLazyDataModel(paginator, paginatorOld, offset, rowPage.get(), totalRecords, sortBy);

        } else {

            /**
             * Utiliza rowPageWithOverlayPanel para el OverlayPanel
             */
            list = processLazyDataModel(paginator, paginatorOld, offset, rowPageSmall.get(), totalRecords, sortBy);

        }
//

        paginator = list.get(0);
        paginatorOld = list.get(1);
        Pagination pagination = new Pagination();
        if (!isRowPageSmall) {

            paginator.setNumberOfPage(numberOfPages(totalRecords, rowPage.get()));
            pagination = new Pagination(paginator.getPage(), rowPage.get());
        } else {

            paginator.setNumberOfPage(numberOfPages(totalRecords, rowPageSmall.get()));
            pagination = new Pagination(paginator.getPage(), rowPageSmall.get());
        }

        List<Tarjeta> result = new ArrayList<>();

        if (textDescripcionToSearch == null || textDescripcionToSearch.equals("")) {
            result = tarjetaServices.searchLikeByTarjeta(textToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get());
        } else {
            if ((textToSearch == null || textToSearch.equals("")) && (textDescripcionToSearch != null || !textDescripcionToSearch.equals(""))) {
                result = tarjetaServices.searchLikeByDescripcion(textDescripcionToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get());
            } else {
              result = tarjetaServices.searchLikeByTarjeta(textToSearch, paginator.getFilter(), paginator.getSort(), paginator.getPage(), rowPageSmall.get());
            }
        }



        tarjetaLazyDataModel.setRowCount(totalRecords);

        PrimeFaces.current().executeScript("setDataTableWithPageStart()");
        PrimeFaces.current().executeScript("widgetVardataTable.getPaginator().setPage(0);");
        tarjetaList = result;

        return result;
    }

    @Override
    public int count(Map<String, FilterMeta> map) {

        return totalRecords;

    }

    @Override
    public String getRowKey(Tarjeta object) {
        if (object == null || object.getIdtarjeta() == null) {
            return "";
        }
        return object.getIdtarjeta().toString();
    }

    @Override
    public Tarjeta getRowData(String rowKey) {
        for (Tarjeta t : tarjetaList) {
            if (t != null) {
                if (t.getIdtarjeta().equals(rowKey)) {
                    return t;
                }
            }
        }
        return null;
    }

};

```
En la siguiente sección se muestra los comportamientos de los eventos.