DEV Community

aristides villarreal
aristides villarreal

Posted on

Implementando searchLikeBy en MongoDB con Jmoordbcore 1/3

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
En JmoordbCore es posible utilizar la anotación @SearchByLike, para generar consultas utilizando expresiones regulares combinadas. Por ejemplo:

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

En este ejemplo utilizaremos un Microservicio que utiliza https://microprofile.io/ con una base de datos MongoDB, que se comunica mediante Jmoordbcore.

Image description

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

Image description

Las interfaces de usuario se desarrollan utilizando Jakarta Faces con Primefaces, como se muestra en la siguiente figura:

Image description

Pasos:

  1. Cree un proyecto Jakarta EE con Payara Starter https://start.payara.fish/
  2. Agregue la dependencia de jmoordbcore
  <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>
Enter fullscreen mode Exit fullscreen mode
  1. Agrega propiedades de conexión a la base de datos en el archivo microprofile-config.properties

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

Enter fullscreen mode Exit fullscreen mode
  1. Defina la entidad Tarjeta que representa un documento de la colección
@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() {
    }

...
}
Enter fullscreen mode Exit fullscreen mode
  1. Defina el repositorio TarjetaRepository.java, con métodos para contar los documentos y realizar búsquedas combinando expresiones regulares con otros filtros.
@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);

}
Enter fullscreen mode Exit fullscreen mode
  1. Cree una clase controladora llamada TarjetaController.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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Creando el Cliente
Pasos:

  1. Cree un proyecto nuevo con Cree un proyecto Jakarta EE con Payara Starter https://start.payara.fish/

  2. Agregue al archivo microprofile-config.properties restclient

com.sft.restclient.TarjetaRestClient/mp-rest/url=http://localhost:9002/accreditation/api/
Enter fullscreen mode Exit fullscreen mode
  1. Cree la entidad tarjeta que definió en el microservicio.

  2. Cree las interfaces para el endpoint tarjeta

@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);

Enter fullscreen mode Exit fullscreen mode
  1. Cree la interface TarjetaServices
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);

}


Enter fullscreen mode Exit fullscreen mode
  1. Cree la implementación
@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;
    }


}

Enter fullscreen mode Exit fullscreen mode
  1. Diseñe la interface de usuario con Jakarta Server Faces y Primefaces para realizar búsquedas, quedando de la siguiente manera:

Interface de usuario

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>
...
Enter fullscreen mode Exit fullscreen mode

Formulario de búsquedas

  1. Cree la clase BuscadorTarjetasFaces
@Named
@ViewScoped
@Data
public class BuscadorTarjetasFaces implements Serializable, JmoordbCoreXHTMLUtil, IPaginator, SprintFacesServices {


@Inject
TarjetaServices tarjetaServices;


Enter fullscreen mode Exit fullscreen mode

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

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;
    }

};

Enter fullscreen mode Exit fullscreen mode

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

Top comments (2)

Collapse
 
avbravo profile image
aristides villarreal

Muchas gracias amigo

Collapse
 
geovanny0401 profile image
Geovanny Mendoza

Excelente articulo amigo