API do Construtor de consulta query-builder-api
A funcionalidade do Construtor de consultas de compartilhamento de ativos é exposta por meio de uma API Java e uma REST API. Esta seção descreve essas APIs.
O construtor de consultas do lado do servidor ( QueryBuilder
) aceitará uma descrição de consulta, criará e executará uma consulta XPath, filtrará opcionalmente o conjunto de resultados e também extrairá facetas, se desejado.
A descrição da consulta é simplesmente um conjunto de predicados (Predicate
). Os exemplos incluem um predicado de texto completo, que corresponde à variável jcr:contains()
no XPath.
Para cada tipo de predicado, há um componente avaliador (PredicateEvaluator
) que sabe como lidar com esse predicado específico para XPath, filtragem e extração de facetas. É muito fácil criar avaliadores personalizados, que são conectados por meio do tempo de execução do componente OSGi.
A REST API fornece acesso a exatamente os mesmos recursos por meio de HTTP, com respostas sendo enviadas em JSON.
Sessão Gem gem-session
AEM Gems O é uma série de aprofundamentos técnicos fornecidos por especialistas em Adobe. Essa sessão dedicada ao construtor de consultas é muito útil para obter uma visão geral e usar a ferramenta.
Consultas de exemplo sample-queries
Essas amostras são fornecidas na notação do estilo das propriedades Java. Para usá-los com a API do Java, use um Java HashMap
como na amostra de API a seguir.
Para o QueryBuilder
Servlet JSON, cada exemplo inclui um link para sua instalação local do CQ (no local padrão, http://localhost:4502
). Observe que é necessário fazer logon na instância do CQ antes de usar esses links.
p.limit=-1
Retorno de todos os resultados returning-all-results
O seguinte query retornar dez resultados (ou, para ser preciso, no máximo dez), mas informe o usuário sobre o Número de ocorrências: que estão efetivamente disponíveis:
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
A mesma consulta (com o parâmetro p.limit=-1
) retornar todos os resultados (pode ser um número alto, dependendo da sua instância):
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
Usar p.guessTotal para retornar os resultados using-p-guesstotal-to-return-the-results
O objetivo da p.guessTotal
é retornar o número adequado de resultados que podem ser mostrados ao combinar os valores mínimo viável de p.offset e p.limit. A vantagem de usar esse parâmetro é o desempenho aprimorado com grandes conjuntos de resultados. Isso evita calcular o total completo (por exemplo, chamar result.getSize()) e ler todo o conjunto de resultados, otimizado até o mecanismo e índice OAK. Essa pode ser uma diferença significativa quando há 100 milhares de resultados, tanto no tempo de execução quanto no uso da memória.
A desvantagem do parâmetro é que os usuários não veem o total exato. Mas você pode definir um número mínimo como p.guessTotal=1000 para que ele sempre leia até 1000, para que você obtenha totais exatos para conjuntos de resultados menores, mas se for mais do que isso, você só poderá mostrar "e mais".
Adicionar p.guessTotal=true
para a query abaixo para ver como 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
O query retornará a variável p.limit
padrão de 10
resultados com um 0
offset:
"success": true,
"results": 10,
"total": 10,
"more": true,
"offset": 0,
A partir do AEM 6.0 SP2, você também poderá usar um valor numérico para contar até um número personalizado de resultados máximos. Use a mesma consulta como acima, mas altere o valor de p.guessTotal
para 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
Ele retornará um número com o mesmo limite padrão de 10 resultados com um deslocamento 0, mas exibirá apenas um máximo de 50 resultados:
"success": true,
"results": 10,
"total": 50,
"more": true,
"offset": 0,
Implementação de paginação implementing-pagination
Por padrão, o Construtor de consultas também forneceria o número de ocorrências. Dependendo do tamanho do resultado, isso pode demorar muito tempo, pois determinar a contagem precisa envolve verificar cada resultado para o controle de acesso. A maioria do total é usada para implementar a paginação da interface do usuário final. Como determinar a contagem exata pode ser lenta, é recomendável usar o recurso guessTotal para implementar a paginação.
Por exemplo, a interface do usuário pode adaptar a seguinte abordagem:
-
Obter e exibir a contagem precisa do número total de ocorrências (SearchResult.getTotalMatches() ou total na resposta de querybuilder.json) são menor ou igual a 100;
-
Definir
guessTotal
para 100 ao fazer a chamada para o Construtor de consultas. -
A resposta pode ter o seguinte resultado:
total=43
,more=false
- Indica que o número total de ocorrências é 43. A interface do usuário pode exibir até dez resultados como parte da primeira página e fornecer paginação para as próximas três páginas. Também é possível usar essa implementação para exibir um texto descritivo como "43 resultados encontrados".total=100
,more=true
- Indica que o número total de ocorrências é maior que 100 e que a contagem exata não é conhecida. A interface do usuário pode exibir até dez como parte da primeira página e fornecer paginação para as próximas dez páginas. Também é possível usar essa opção para exibir um texto como "mais de 100 resultados encontrados". À medida que o usuário vai para as próximas páginas, as chamadas feitas para o Construtor de consultas aumentariam o limite deguessTotal
e também daoffset
elimit
parâmetros.
guessTotal
também deve ser usada em casos em que a interface do usuário precisa usar a rolagem infinita, para evitar que o Construtor de consultas determine a contagem exata de ocorrências.
Encontre arquivos jar e ordene-os, primeiro mais recentes find-jar-files-and-order-them-newest-first
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
Encontre todas as páginas e ordene-as pela última modificação find-all-pages-and-order-them-by-last-modified
http://localhost:4502/bin/querybuilder.json?type=cq:Page&orderby=@jcr:content/cq:lastModified
type=cq:Page
orderby=@jcr:content/cq:lastModified
Encontre todas as páginas e ordene-as pela última modificação, mas decrescente find-all-pages-and-order-them-by-last-modified-but-descending
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
Pesquisa de texto completo, ordenada por pontuação fulltext-search-ordered-by-score
http://localhost:4502/bin/querybuilder.json?fulltext=Management&orderby=@jcr:score&orderby.sort=desc
fulltext=Management
orderby=@jcr:score
orderby.sort=desc
Pesquisar páginas marcadas com uma determinada tag search-for-pages-tagged-with-a-certain-tag
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 o tagid
predicado como no exemplo, se você souber a ID de tag explícita.
Use o tag
predicado para o caminho do título da tag (sem espaços).
Como, no exemplo anterior, você está pesquisando por páginas ( cq:Page
nós), você precisa usar o caminho relativo desse nó para o tagid.property
predicado, que é jcr:content/cq:tags
. Por padrão, a variável tagid.property
seria simplesmente cq:tags
.
Pesquisar em vários caminhos (usando grupos) search-under-multiple-paths-using-groups
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
Esse query usa uma grupo (nomeado como " group
"), que atua para delimitar subexpressões em um query, assim como os parênteses fazem em notações mais padrão. Por exemplo, a consulta anterior pode ser expressa em um estilo mais familiar como:
"Management" and ("/content/geometrixx/en/company/management" or "/content/geometrixx/en/company/bod")
No grupo do exemplo, a variável path
predicado é usado várias vezes. Para diferenciar e ordenar as duas instâncias do predicado (a ordem é necessária para alguns predicados), você deve prefixar os predicados com N _ where
N é o índice de pedido. No exemplo anterior, os predicados resultantes são 1_path
e 2_path
.
O p
em p.or
é um delimitador especial indicando o que segue (neste caso, um or
) é um parâmetro do grupo, por oposição a um subpredicado do grupo, como 1_path
.
Se não p.or
é dado então todos os predicados são AND, ou seja, cada resultado deve satisfazer todos os predicados.
Pesquisar propriedades search-for-properties
Aqui você está procurando por todas as páginas de um determinado modelo, usando o cq:template
propriedade:
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
Isso tem a desvantagem de que a variável jcr:content
os nós das páginas, não as próprias páginas, são retornados. Para resolver isso, você pode pesquisar por caminho relativo:
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
Procurar várias propriedades search-for-multiple-properties
Ao usar o predicado de propriedade várias vezes, é necessário adicionar os prefixos de número novamente:
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
Pesquisar por vários valores de propriedade search-for-multiple-property-values
Para evitar grandes grupos quando você deseja pesquisar por vários valores de uma propriedade ( "A" or "B" or "C"
), é possível fornecer vários valores para a variável 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 propriedades de vários valores, também é possível exigir que vários valores correspondam a ( "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 o que é retornado refining-what-is-returned
Por padrão, o Servlet JSON do QueryBuilder retornará um conjunto padrão de propriedades para cada nó no resultado da pesquisa (por exemplo, caminho, nome, título etc.). Para obter controle sobre quais propriedades são retornadas, é possível fazer o seguinte:
Especifique
p.hits=full
nesse caso, todas as propriedades serão incluídas para cada nó:
http://localhost:4502/bin/querybuilder.json?p.hits=full&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=full
Utilização
p.hits=selective
e especifique as propriedades que deseja obter
p.properties
separados por um espaço:
http://localhost:4502/bin/querybuilder.json?p.hits=selective&property=jcr%3atitle&property.value=Triangle
http://localhost:4502/bin/querybuilder.json?
p.hits=seletivo&p.properties=sling%3aresourceType%20jcr%3primaryType&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=selective
p.properties=sling:resourceType jcr:primaryType
Outra coisa que você pode fazer é incluir nós filhos na resposta do QueryBuilder. Para fazer isso, você precisa especificar
p.nodedepth=n
em que n
é o número de níveis que você deseja que a consulta retorne. Observe que, para que um nó filho seja retornado, ele deve ser especificado pelo seletor de propriedades
p.hits=full
Exemplo:
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
Mais Predicados morepredicates
Para obter mais predicados, consulte a Página Referência do predicado do construtor de consultas.
Você também pode verificar a variável Javadoc para a PredicateEvaluator
classes. O Javadoc para essas classes contém a lista de propriedades que você pode usar.
O prefixo do nome da classe (por exemplo, " similar
" in SimilarityPredicateEvaluator
) é a variável propriedade principal da classe. Essa propriedade também é o nome do predicado a ser usado na query (em minúsculas).
Para essas propriedades principais, você pode encurtar a consulta e usar " similar=/content/en
" em vez da variante totalmente qualificada " similar.similar=/content/en
". O formulário totalmente qualificado deve ser usado para todas as propriedades não principais de uma classe.
Exemplo de uso da API do Query Builder example-query-builder-api-usage
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 );
}
O mesmo query executada por HTTP usando o Servlet do Construtor de Consultas (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
Armazenamento e carregamento de consultas storing-and-loading-queries
As consultas podem ser armazenadas no repositório para que você possa usá-las posteriormente. O QueryBuilder
fornece o " storeQuery
método com a seguinte assinatura:
void storeQuery(Query query, String path, boolean createFile, Session session) throws RepositoryException, IOException;
Ao usar a variável QueryBuilder#storeQuery
método , o dado Query
é armazenado no repositório como um arquivo ou como uma propriedade de acordo com a variável createFile
valor do argumento. O exemplo a seguir mostra como salvar um Query
para o caminho /mypath/getfiles
como arquivo:
builder.storeQuery(query, "/mypath/getfiles", true, session);
Quaisquer consultas armazenadas anteriormente podem ser carregadas do repositório usando o QueryBuilder#loadQuery
método :
Query loadQuery(String path, Session session) throws RepositoryException, IOException
Por exemplo, um Query
armazenado no caminho /mypath/getfiles
pode ser carregado pelo seguinte trecho:
Query loadedQuery = builder.loadQuery("/mypath/getfiles", session);
Teste e depuração testing-and-debugging
Para reproduzir e depurar consultas do querybuilder, você pode usar o console do QueryBuilder Debugger em
http://localhost:4502/libs/cq/search/content/querydebug.html
ou, alternativamente, o servlet json do querybuilder em
http://localhost:4502/bin/querybuilder.json?path=/tmp
( path=/tmp
é apenas um exemplo).
Depuração geral do Recommendations general-debugging-recommendations
Obter XPath explicável via registro obtain-explain-able-xpath-via-logging
Explicar all consultas durante o ciclo de desenvolvimento em relação ao conjunto de índices de destino.
-
Habilite logs DEBUG para o QueryBuilder para obter consulta XPath subjacente explicável
- Navegue até https://<serveraddress>:<serverport>/system/console/slinglog. Criar um novo logger para
com.day.cq.search.impl.builder.QueryImpl
at DEPURAR.
- Navegue até https://<serveraddress>:<serverport>/system/console/slinglog. Criar um novo logger para
-
Depois que DEBUG for ativado para a classe acima, os logs exibirão o XPath gerado pelo Query Builder.
-
Copie a consulta XPath da entrada de log para a consulta QueryBuilder associada, Por exemplo:
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"))]
-
Cole a consulta XPath em Explicar Consulta como XPath para obter o plano de consulta
Obter XPath explicável por meio do depurador do Query Builder obtain-explain-able-xpath-via-the-query-builder-debugger
- Use o AEM QueryBuilder Debugger para gerar uma consulta XPath explicável:
Explicar all consultas durante o ciclo de desenvolvimento em relação ao conjunto de índices de destino.
Obter XPath explicável via registro
-
Habilite logs DEBUG para o QueryBuilder para obter consulta XPath subjacente explicável
- Navegue até https://<serveraddress>:<serverport>/system/console/slinglog. Criar um novo logger para
com.day.cq.search.impl.builder.QueryImpl
at DEPURAR.
- Navegue até https://<serveraddress>:<serverport>/system/console/slinglog. Criar um novo logger para
-
Depois que DEBUG for ativado para a classe acima, os logs exibirão o XPath gerado pelo Query Builder.
-
Copie a consulta XPath da entrada de log para a consulta QueryBuilder associada, Por exemplo:
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"))]
-
Cole a consulta XPath em Explicar Consulta como XPath para obter o plano de consulta
Obter XPath explicável por meio do depurador do Query Builder
- Use o AEM QueryBuilder Debugger para gerar uma consulta XPath explicável:
- Forneça a consulta do Construtor de consultas no depurador do Construtor de consultas
- Executar a pesquisa
- Obter o XPath gerado
- Cole a consulta XPath na Consulta Explain como XPath para obter o plano de consulta
Para obter um resumo sobre como depurar consultas com o QueryBuilder, consulte o vídeo abaixo.
Depuração de consultas com registro debugging-queries-with-logging
A saída do log (nível INFO) da implementação do construtor de consultas ao executar a consulta descrita em Testes e Depuração:
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
Se você tiver uma consulta usando avaliadores de predicado que filtram ou usam um pedido personalizado por comparador, isso também será observado na 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