Show Menu
TEMAS×

API de Consulta Builder

La funcionalidad del Generador de Consultas de uso compartido de recursos se expone mediante una API de Java y una API de REST. Esta sección describe estas API.
El generador de consultas del lado del servidor ( QueryBuilder ) aceptará una descripción de la consulta, creará y ejecutará una consulta XPath, opcionalmente filtrará el conjunto de resultados y también extraerá facetas, si lo desea.
La descripción de la consulta es simplemente un conjunto de predicados ( Predicate ). Algunos ejemplos incluyen un predicado de texto completo, que corresponde a la jcr:contains() función en XPath.
Para cada tipo de predicado, hay un componente ( PredicateEvaluator ) de evaluador que sabe cómo manejar ese predicado específico para XPath, filtrado y extracción de facetas. Es muy fácil crear evaluadores personalizados, que se conectan a través del tiempo de ejecución del componente OSGi.
La API de REST proporciona acceso a exactamente las mismas funciones a través de HTTP y las respuestas se envían en JSON.
La API de QueryBuilder se crea mediante la API de JCR. También puede realizar la consulta del JCR de Adobe Experience Manager mediante la API de JCR desde un paquete OSGi. Para obtener más información, consulte Consulta de datos de Adobe Experience Manager mediante la API de JCR.

Sesión de Gem

AEM Gems es una serie de inmersiones técnicas en Adobe Experience Manager realizadas por expertos de Adobe. Esta sesión dedicada al generador de consultas es muy útil para una visión general y el uso de la herramienta.
Consulte la sesión de AEM Gem Buscar formularios fácilmente con el querybuilder de AEM para obtener una descripción detallada del generador de consultas.

Consultas de muestra

Estos ejemplos se proporcionan en notación de estilo de las propiedades Java. Para utilizarlos con la API de Java, utilice un Java HashMap como en el ejemplo de API que se muestra a continuación.
Para el servlet QueryBuilder JSON, cada ejemplo incluye un vínculo a la instalación local de CQ (en la ubicación predeterminada, http://localhost:4502 ). Tenga en cuenta que debe iniciar sesión en la instancia de CQ antes de utilizar estos vínculos.
De forma predeterminada, el servlet json del generador de consultas muestra un máximo de 10 visitas.
Añadir el siguiente parámetro permite que el servlet muestre todos los resultados de la consulta:
p.limit=-1
Para vista de los datos JSON devueltos en el navegador, puede que desee utilizar un complemento como JSONView para Firefox.

Devolución de todos los resultados

La siguiente consulta devolverá diez resultados (o para ser precisos, un máximo de diez), pero le informará del número de visitas: que están realmente disponibles:
http://localhost:4502/bin/querybuilder.json?path=/content&1_property=sling:resourceType&1_property.value=foundation/components/text&1_property.operation=like&orderby=path
path=/content
1_property=sling:resourceType
1_property.value=foundation/components/text
1_property.operation=like
orderby=path

La misma consulta (con el parámetro p.limit=-1 ) devolverá todos los resultados (puede ser un número elevado en función de la instancia):
http://localhost:4502/bin/querybuilder.json?path=/content&1_property=sling:resourceType&1_property.value=foundation/components/text&1_property.operation=like&p.limit=-1&orderby=path
path=/content
1_property=sling:resourceType
1_property.value=foundation/components/text
1_property.operation=like
p.limit=-1
orderby=path

Uso de p.imagestotal para devolver los resultados

El propósito del p.guessTotal parámetro es devolver el número apropiado de resultados que se pueden mostrar combinando los valores mínimos viables de p.offset y p.limit. La ventaja de utilizar este parámetro es que se ha mejorado el rendimiento con grandes conjuntos de resultados. Esto evita calcular el total completo (por ejemplo, llamando a result.getSize()) y leer todo el conjunto de resultados, optimizado hasta el motor y el índice OAK. Esto puede ser una diferencia significativa cuando hay 100 mil resultados, tanto en el tiempo de ejecución como en el uso de la memoria.
La desventaja del parámetro es que los usuarios no ven el total exacto. Pero se puede establecer un número mínimo como p.adivinenTotal=1000 para que siempre se lea hasta 1000, así se obtienen los totales exactos para los conjuntos de resultados más pequeños, pero si es mayor que eso, solo se puede mostrar "y más".
Añada p.guessTotal=true a la consulta siguiente para ver cómo funciona:
http://localhost:4502/bin/querybuilder.json?path=/content&1_property=sling:resourceType&1_property.value=foundation/components/text&1_property.operation=like&p.guessTotal=true&orderby=path
path=/content
1_property=sling:resourceType
1_property.value=foundation/components/text
1_property.operation=like
p.guessTotal=true
orderby=path

La consulta devolverá el p.limit valor predeterminado de 10 resultados con un 0 desplazamiento:
"success": true,
"results": 10,
"total": 10,
"more": true,
"offset": 0,

A partir de AEM 6.0 SP2, también puede utilizar un valor numérico para contar hasta un número personalizado de resultados máximos. Utilice la misma consulta que la anterior, pero cambie el valor de p.guessTotal a 50 :
http://localhost:4502/bin/querybuilder.json?path=/content&1_property=sling:resourceType&1_property.value=foundation/components/text&1_property.operation=like&p.guessTotal=50&orderby=path
Devolverá un número con el mismo límite predeterminado de 10 resultados con un desplazamiento de 0, pero solo mostrará un máximo de 50 resultados:
"success": true,
"results": 10,
"total": 50,
"more": true,
"offset": 0,

Implementación de paginación

De forma predeterminada, el Generador de Consultas también proporciona el número de visitas. Dependiendo del tamaño del resultado, esto puede llevar mucho tiempo ya que determinar el recuento exacto implica comprobar cada resultado en busca de controles de acceso. Principalmente, el total se utiliza para implementar la paginación para la interfaz de usuario del usuario final. Dado que determinar el recuento exacto puede ser lento, se recomienda utilizar la función adivinar total para implementar la paginación.
Por ejemplo, la interfaz de usuario puede adaptar el siguiente método:
  • Obtener y mostrar el recuento preciso del número total de visitas ( SearchResult.getTotalMatches() o total en la respuesta querybuilder.json) es menor o igual a 100;
  • Establezca guessTotal en 100 mientras realiza la llamada al Generador de Consultas.
  • La respuesta puede tener el siguiente resultado:
    • total=43 , more=false : indica que el número total de visitas es de 43. La interfaz de usuario puede mostrar hasta diez resultados como parte de la primera página y proporcionar paginación para las tres páginas siguientes. También puede utilizar esta implementación para mostrar un texto descriptivo como "43 resultados encontrados" .
    • total=100 , more=true : indica que el número total de visitas es bueno a más de 100 y que no se conoce el recuento exacto. La interfaz de usuario puede mostrar hasta diez como parte de la primera página y proporcionar paginación para las diez páginas siguientes. También puede utilizarla para mostrar un texto como "se encontraron más de 100 resultados" . A medida que el usuario va a las páginas siguientes, las llamadas realizadas al Generador de Consultas aumentarán el límite de guessTotal y también de los parámetros offset y limit .
guessTotal también debe utilizarse en casos en los que la interfaz de usuario necesite utilizar el desplazamiento infinito, para evitar que el Generador de Consultas determine el recuento exacto de visitas.

Buscar archivos jar y ordenarlos, los más recientes primero

http://localhost:4502/bin/querybuilder.json?type=nt:file&nodename=*.jar&orderby=@jcr:content/jcr:lastModified&orderby.sort=desc
type=nt:file
nodename=*.jar
orderby=@jcr:content/jcr:lastModified
orderby.sort=desc

Buscar todas las páginas y pedirlas por última vez

http://localhost:4502/bin/querybuilder.json?type=cq:Page&orderby=@jcr:content/cq:lastModified
type=cq:Page
orderby=@jcr:content/cq:lastModified

Buscar todas las páginas y ordenarlas por última vez modificadas, pero en orden descendente

http://localhost:4502/bin/querybuilder.json?type=cq:Page&orderby=@jcr:content/cq:lastModified&orderby.sort=desc]
type=cq:Page
orderby=@jcr:content/cq:lastModified
orderby.sort=desc

Búsqueda de texto completo, ordenada por puntuación

http://localhost:4502/bin/querybuilder.json?fulltext=Management&orderby=@jcr:score&orderby.sort=desc
fulltext=Management
orderby=@jcr:score
orderby.sort=desc

Buscar páginas etiquetadas con una etiqueta determinada

`http://localhost:4502/bin/querybuilder.json?type=cq:Page&tagid=marketing:interest/product&tagid.property=jcr:content/cq:tags'
type=cq:Page
tagid=marketing:interest/product
tagid.property=jcr:content/cq:tags

Use el tagid predicado como en el ejemplo si conoce el ID de etiqueta explícito.
Utilice el tag predicado para la ruta de título de la etiqueta (sin espacios).
Dado que, en el ejemplo anterior, está buscando páginas ( cq:Page nodos), debe utilizar la ruta relativa desde ese nodo para el tagid.property predicado, que es jcr:content/cq:tags . De manera predeterminada, tagid.property simplemente lo sería cq:tags .

Buscar en varias rutas (mediante grupos)

http://localhost:4502/bin/querybuilder.json?fulltext=Management&group.1_path=/content/geometrixx/en/company/management&group.2_path=/content/geometrixx/en/company/bod&group.p.or=true
fulltext=Management
group.p.or=true
group.1_path=/content/geometrixx/en/company/management
group.2_path=/content/geometrixx/en/company/bod

Esta consulta utiliza un grupo (denominado " group "), que actúa para delimitar subexpresiones dentro de una consulta, de manera similar a como lo hacen los paréntesis en las anotaciones más estándar. Por ejemplo, la consulta anterior podría expresarse con un estilo más familiar:
"Management" and ("/content/geometrixx/en/company/management" or "/content/geometrixx/en/company/bod")
Dentro del grupo en el ejemplo, el path predicado se utiliza varias veces. Para diferenciar y ordenar las dos instancias del predicado (se requiere orden para algunos predicados), debe anteponer los predicados con N _ where *N *es el índice de ordenación. En el ejemplo anterior, los predicados resultantes son 1_path y 2_path .
El p in p.or es un delimitador especial que indica que lo que sigue (en este caso, un or ) es un parámetro del grupo, en lugar de un subpredicado del grupo, como 1_path .
Si no p.or se proporciona ningún predicado, entonces todos los predicados son Yed juntos, es decir, cada resultado debe satisfacer todos los predicados.
No se puede utilizar el mismo prefijo numérico en una sola consulta, ni siquiera para predicados diferentes.

Buscar propiedades

Aquí está buscando todas las páginas de una plantilla determinada, utilizando la cq:template propiedad:
http://localhost:4502/bin/querybuilder.json?property=cq%3atemplate&property.value=%2fapps%2fgeometrixx%2ftemplates%2fhomepage&type=cq%3aPageContent
type=cq:PageContent
property=cq:template
property.value=/apps/geometrixx/templates/homepage

Esto tiene el inconveniente de que se devuelven los jcr:content nodos de las páginas, no las páginas mismas. Para solucionarlo, puede buscar por ruta relativa:
http://localhost:4502/bin/querybuilder.json?property=jcr%3acontent%2fcq%3atemplate&property.value=%2fapps%2fgeometrixx%2ftemplates%2fhomepage&type=cq%3aPage
type=cq:Page
property=jcr:content/cq:template
property.value=/apps/geometrixx/templates/homepage

Buscar varias propiedades

Cuando se utiliza el predicado de propiedades varias veces, hay que volver a agregar los prefijos numéricos:
http://localhost:4502/bin/querybuilder.json?1_property=jcr%3acontent%2fcq%3atemplate&1_property.value=%2fapps%2fgeometrixx%2ftemplates%2fhomepage&2_property=jcr%3acontent%2fjcr%3atitle&2_property.value=English&type=cq%3aPage
type=cq:Page
1_property=jcr:content/cq:template
1_property.value=/apps/geometrixx/templates/homepage
2_property=jcr:content/jcr:title
2_property.value=English

Buscar varios valores de propiedad

Para evitar grupos grandes cuando desee buscar valores múltiples de una propiedad ( "A" or "B" or "C" ), puede proporcionar varios valores al property predicado:
http://localhost:4502/bin/querybuilder.json?property=jcr%3atitle&property.1_value=Products&property.2_value=Square&property.3_value=Events
property=jcr:title
property.1_value=Products
property.2_value=Square
property.3_value=Events

Para propiedades de varios valores, también puede requerir que coincidan varios valores ( "A" and "B" and "C" ):
http://localhost:4502/bin/querybuilder.json?property=jcr%3atitle&property.and=true&property.1_value=test&property.2_value=foo&property.3_value=bar
property=jcr:title
property.and=true
property.1_value=test
property.2_value=foo
property.3_value=bar

Refinar lo que se devuelve

De forma predeterminada, el servlet JSON de QueryBuilder devolverá un conjunto predeterminado de propiedades para cada nodo del resultado de búsqueda (por ejemplo, ruta, nombre, título, etc.). Para obtener el control sobre qué propiedades se devuelven, puede realizar una de las siguientes acciones:
Especificar
p.hits=full

en cuyo caso se incluirán todas las propiedades de cada nodo:
http://localhost:4502/bin/querybuilder.json?p.hits=full&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=full

Uso
p.hits=selective

y especifique las propiedades en las que desea entrar
p.properties

separado por un espacio:
http://localhost:4502/bin/querybuilder.json?p.hits=selective&property=jcr%3atitle&property.value=Triangle
http://localhost:4502/bin/querybuilder.json? p. hits=selectivo& p.properties=sling%3aresourceType%20jcr%3primariaType&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=selective
p.properties=sling:resourceType jcr:primaryType

Otra cosa que puede hacer es incluir nodos secundarios en la respuesta de QueryBuilder. Para ello, debe especificar
p.nodedepth=n

donde n es el número de niveles que desea que la consulta devuelva. Tenga en cuenta que, para que se devuelva un nodo secundario, debe especificarlo el selector de propiedades
p.hits=full

Ejemplo:
http://localhost:4502/bin/querybuilder.json?p.hits=full&p.nodedepth=5&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=full
p.nodedepth=5

Más predicados

Para obtener más predicados, consulte la página Referencia de predicado del generador de Consultas.
También puede consultar el Javadoc para las . El Javadoc de estas clases contiene la lista de propiedades que puede utilizar.
El prefijo del nombre de clase (por ejemplo, " similar " en SimilarityPredicateEvaluator ) es la propiedad ** principal de la clase. Esta propiedad también es el nombre del predicado que se va a usar en la consulta (en minúscula).
Para estas propiedades principales, puede abreviar la consulta y utilizar " similar=/content/en " en lugar de la variante completa " similar.similar=/content/en ". El formulario completo debe utilizarse para todas las propiedades no principales de una clase.

Ejemplo de uso de la API del Generador de Consultas

   String fulltextSearchTerm = "Geometrixx";

    // create query description as hash map (simplest way, same as form post)
    Map<String, String> map = new HashMap<String, String>();
  
// create query description as hash map (simplest way, same as form post)
    map.put("path", "/content");
    map.put("type", "cq:Page");
    map.put("group.p.or", "true"); // combine this group with OR
    map.put("group.1_fulltext", fulltextSearchTerm);
    map.put("group.1_fulltext.relPath", "jcr:content");
    map.put("group.2_fulltext", fulltextSearchTerm);
    map.put("group.2_fulltext.relPath", "jcr:content/@cq:tags");
 
    // can be done in map or with Query methods
    map.put("p.offset", "0"); // same as query.setStart(0) below
    map.put("p.limit", "20"); // same as query.setHitsPerPage(20) below

    Query query = builder.createQuery(PredicateGroup.create(map), session);
    query.setStart(0);
    query.setHitsPerPage(20);

    SearchResult result = query.getResult();
 
    // paging metadata
    int hitsPerPage = result.getHits().size(); // 20 (set above) or lower
    long totalMatches = result.getTotalMatches();
    long offset = result.getStartIndex();
    long numberOfPages = totalMatches / 20;

    //Place the results in XML to return to client
    DocumentBuilderFactory factory =     DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.newDocument();

    //Start building the XML to pass back to the AEM client
    Element root = doc.createElement( "results" );
    doc.appendChild( root );

    // iterating over the results
    for (Hit hit : result.getHits()) {
       String path = hit.getPath();
 
      //Create a result element
      Element resultel = doc.createElement( "result" );
      root.appendChild( resultel );

      Element pathel = doc.createElement( "path" );
      pathel.appendChild( doc.createTextNode(path ) );
      resultel.appendChild( pathel );
    }

Para obtener información sobre cómo crear un paquete OSGi que utilice la API de QueryBuilder y ese paquete OSGi en una aplicación de Adobe Experience Manager, consulte Creación de paquetes OSGi de Adobe CQ que utilicen la API de Consulta Builder.
La misma consulta ejecutada a través de HTTP mediante el servlet Consulta Builder (JSON):
http://localhost:4502/bin/querybuilder.json?path=/content&type=cq:Page&group.p.or=true&group.1_fulltext=Geometrixx&group.1_fulltext.relPath=jcr:content&group.2_fulltext=Geometrixx&group.2_fulltext.relPath=jcr:content/@cq:tags&p.offset=0&p.limit=20

Almacenamiento y carga de consultas

Las Consultas se pueden almacenar en el repositorio para que pueda usarlas más adelante. El QueryBuilder proporciona el " storeQuery método con la siguiente firma:
void storeQuery(Query query, String path, boolean createFile, Session session) throws RepositoryException, IOException;

Al utilizar el método , el determinado Query se almacena en el repositorio como archivo o como propiedad según el valor del createFile argumento. En el siguiente ejemplo se muestra cómo guardar un archivo Query en la ruta /mypath/getfiles como archivo:
builder.storeQuery(query, "/mypath/getfiles", true, session);

Las consultas almacenadas anteriormente se pueden cargar desde el repositorio mediante el QueryBuilder#loadQuery método:
Query loadQuery(String path, Session session) throws RepositoryException, IOException

Por ejemplo, un fragmento Query almacenado en la ruta de acceso /mypath/getfiles puede cargarse con el siguiente fragmento:
Query loadedQuery = builder.loadQuery("/mypath/getfiles", session);

Pruebas y depuración

Para reproducir y depurar consultas de querybuilder, puede utilizar la consola de depuración de QueryBuilder en
http://localhost:4502/libs/cq/search/content/querydebug.html
o bien el servlet json querybuilder en
http://localhost:4502/bin/querybuilder.json?path=/tmp
( path=/tmp es sólo un ejemplo).

Recomendaciones generales de depuración

Obtención de XPath explicable mediante registro

Explicar todas las consultas durante el ciclo de desarrollo con respecto al conjunto de índices de destinatario.
  • Habilitar los registros DEBUG para QueryBuilder para obtener la consulta XPath subyacente y explicable
    • Vaya a https://<serveraddress>:<serverport>/system/console/slinglog. Cree un nuevo registrador para com.day.cq.search.impl.builder.QueryImpl en DEBUG .
  • Una vez que DEBUG se haya habilitado para la clase anterior, los registros mostrarán el XPath generado por el Generador de Consultas.
  • Copie la consulta XPath de la entrada de registro de la consulta asociada de QueryBuilder. Por ejemplo:
    • com.day.cq.search.impl.builder.QueryImpl XPath query: /jcr:root/content//element(*, cq:Page)[(jcr:contains(jcr:content, "Geometrixx") or jcr:contains(jcr:content/@cq:tags, "Geometrixx"))]
  • Pegue la consulta XPath en Explicar Consulta como XPath para cumplir el plan de consulta

Obtenga XPath explicable mediante el depurador de Consulta Builder

  • Utilice el depurador de AEM QueryBuilder para generar una consulta XPath explicable:
Explicar todas las consultas durante el ciclo de desarrollo con respecto al conjunto de índices de destinatario.
Obtención de XPath explicable mediante registro
  • Habilitar los registros DEBUG para QueryBuilder para obtener la consulta XPath subyacente y explicable
    • Vaya a https://<serveraddress>:<serverport>/system/console/slinglog. Cree un nuevo registrador para com.day.cq.search.impl.builder.QueryImpl en DEBUG .
  • Una vez que DEBUG se haya habilitado para la clase anterior, los registros mostrarán el XPath generado por el Generador de Consultas.
  • Copie la consulta XPath de la entrada de registro de la consulta asociada de QueryBuilder. Por ejemplo:
    • com.day.cq.search.impl.builder.QueryImpl XPath query: /jcr:root/content//element(*, cq:Page)[(jcr:contains(jcr:content, "Geometrixx") or jcr:contains(jcr:content/@cq:tags, "Geometrixx"))]
  • Pegue la consulta XPath en Explicar Consulta como XPath para cumplir el plan de consulta
Obtenga XPath explicable mediante el depurador de Consulta Builder
  • Utilice el depurador de AEM QueryBuilder para generar una consulta XPath explicable:
  1. Proporcione la consulta Consulta Builder en el depurador del Generador de Consultas
  2. Ejecutar la búsqueda
  3. Obtenga el XPath generado
  4. Pegue la consulta XPath en Explicar Consulta como XPath para cumplir con el plan de consulta
Las consultas que no son de querybuilder (XPath, JCR-SQL2) se pueden proporcionar directamente para explicar la Consulta.
Para ver un resumen de cómo depurar consultas con QueryBuilder, consulte el siguiente vídeo.

Depuración de Consultas con registro

La configuración de los registradores se describe en la sección Creación de sus propios registradores y escritores .
Salida de registro (nivel INFO) de la implementación del generador de consultas al ejecutar la consulta descrita en Pruebas y depuración:
com.day.cq.search.impl.builder.QueryImpl executing query (predicate tree):
null=group: limit=20, offset=0[
    {group=group: or=true[
        {1_fulltext=fulltext: fulltext=Geometrixx, relPath=jcr:content}
        {2_fulltext=fulltext: fulltext=Geometrixx, relPath=jcr:content/@cq:tags}
    ]}
    {path=path: path=/content}
    {type=type: type=cq:Page}
]
com.day.cq.search.impl.builder.QueryImpl XPath query: /jcr:root/content//element(*, cq:Page)[(jcr:contains(jcr:content, "Geometrixx") or jcr:contains(jcr:content/@cq:tags, "Geometrixx"))]
com.day.cq.search.impl.builder.QueryImpl no filtering predicates
com.day.cq.search.impl.builder.QueryImpl query execution took 69 ms

Si tiene una consulta que utiliza evaluadores predicados que filtren o que utilizan un orden personalizado por comparador, esto también se anotará en la consulta:
com.day.cq.search.impl.builder.QueryImpl executing query (predicate tree):
null=group: [
    {nodename=nodename: nodename=*.jar}
    {orderby=orderby: orderby=@jcr:content/jcr:lastModified}
    {type=type: type=nt:file}
]
com.day.cq.search.impl.builder.QueryImpl custom order by comparator: jcr:content/jcr:lastModified
com.day.cq.search.impl.builder.QueryImpl XPath query: //element(*, nt:file)
com.day.cq.search.impl.builder.QueryImpl filtering predicates: {nodename=nodename: nodename=*.jar}
com.day.cq.search.impl.builder.QueryImpl query execution took 272 ms