Show Menu
ARGOMENTI×

API Query Builder

La funzionalità di Asset Share Query Builder è esposta tramite un'API Java e un'API REST. Questa sezione descrive queste API.
Il generatore di query sul lato server ( QueryBuilder ) accetta una descrizione della query, crea ed esegue una query XPath, eventualmente applica un filtro al set di risultati e, se necessario, estrae anche i facet.
La descrizione della query è semplicemente un insieme di predicati ( Predicate ). Alcuni esempi includono un predicato full-text, che corrisponde alla jcr:contains() funzione in XPath.
Per ciascun tipo di predicato, è presente un componente di valutazione ( PredicateEvaluator ) in grado di gestire tale predicato specifico per XPath, filtraggio ed estrazione dei facet. È molto facile creare valutatori personalizzati, che vengono collegati tramite il runtime dei componenti OSGi.
L'API REST fornisce l'accesso esattamente alle stesse funzionalità tramite HTTP, con le risposte inviate in JSON.
L'API QueryBuilder viene creata utilizzando l'API JCR. Potete anche eseguire una query sul JCR di Adobe Experience Manager utilizzando l'API JCR dall'interno di un bundle OSGi. Per informazioni, consultate Query sui dati di Adobe Experience Manager tramite l'API JCR.

Sessione Gem

AEM Gems è una serie di approfondimenti tecnici di Adobe Experience Manager forniti dagli esperti Adobe. Questa sessione dedicata al generatore di query è molto utile per una panoramica e l'utilizzo dello strumento.
Consulta i moduli di ricerca della sessione AEM Gem semplificati con il querybuilder AEM per una panoramica dettagliata del generatore di query.

Query di esempio

Questi esempi sono riportati nella notazione dello stile delle proprietà Java. Per utilizzarli con l'API Java, utilizzate Java HashMap come nell'esempio di API che segue.
Per il Servlet QueryBuilder JSON, ogni esempio include un collegamento all’installazione locale di CQ (nella posizione predefinita, http://localhost:4502 ). Prima di usare questi collegamenti, è necessario accedere all’istanza CQ.
Per impostazione predefinita, il servlet json del generatore di query visualizza un massimo di 10 hit.
L'aggiunta del seguente parametro consente al servlet di visualizzare tutti i risultati della query:
p.limit=-1
Per visualizzare i dati JSON restituiti nel browser, potresti voler usare un plug-in come JSONView per Firefox.

Restituzione di tutti i risultati

La seguente query restituisce dieci risultati (o, per essere precisi, un massimo di dieci), ma segnala il numero di hit: che sono effettivamente disponibili:
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 stessa query (con il parametro p.limit=-1 ) restituisce tutti i risultati (questo può essere un numero elevato a seconda dell'istanza):
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

Utilizzo di p.impressionTotal per restituire i risultati

Lo scopo del p.guessTotal parametro è di restituire il numero appropriato di risultati che possono essere mostrati combinando i valori p.offset e p.limit minimi. Il vantaggio di utilizzare questo parametro è rappresentato da prestazioni migliori con set di risultati di grandi dimensioni. In questo modo si evita di calcolare il totale totale (ad esempio, chiamando result.getSize()) e di leggere l’intero set di risultati, ottimizzato fino al motore e indice OAK. Ciò può rappresentare una differenza significativa in presenza di 100 migliaia di risultati, sia in termini di tempo di esecuzione che di utilizzo della memoria.
Lo svantaggio per il parametro è che gli utenti non vedono il totale esatto. Ma potete impostare un numero minimo come p.indovinoTotale=1000 in modo che sia sempre letto fino a 1000, quindi ottenete i totali esatti per i set di risultati più piccoli, ma se è più di questo, potete solo mostrare "e più".
Aggiungi p.guessTotal=true alla query seguente per vedere come funziona:
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 query restituirà il p.limit valore predefinito dei 10 risultati con un 0 offset:
"success": true,
"results": 10,
"total": 10,
"more": true,
"offset": 0,

A partire da AEM 6.0 SP2, potete anche utilizzare un valore numerico per conteggiare fino a un numero personalizzato di risultati massimi. Utilizzate la stessa query di cui sopra, ma modificate il valore di p.guessTotal in 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
Verrà restituito un numero con lo stesso limite predefinito di 10 risultati con un offset pari a 0, ma verranno visualizzati solo 50 risultati:
"success": true,
"results": 10,
"total": 50,
"more": true,
"offset": 0,

Implementazione della paginazione

Per impostazione predefinita, Query Builder fornisce anche il numero di hit. A seconda della dimensione del risultato, questo potrebbe richiedere molto tempo, poiché per determinare il conteggio accurato è necessario controllare ogni risultato per il controllo dell'accesso. La maggior parte del totale viene utilizzata per implementare l'impaginazione per l'interfaccia utente finale. Poiché determinare il conteggio esatto può essere lento, si consiglia di utilizzare la funzione approssimativaTotale per implementare l'impaginazione.
Ad esempio, l’interfaccia utente può adattare il seguente approccio:
  • Ottenere e visualizzare il conteggio accurato del numero di hit totali ( SearchResult.getTotalMatches() o totale nella risposta querybuilder.json) è minore o uguale a 100;
  • Impostate guessTotal su 100 durante la chiamata al Generatore di query.
  • La risposta può avere il seguente risultato:
    • total=43 , more=false - Indica che il numero totale di hit è 43. L’interfaccia utente può visualizzare fino a dieci risultati nella prima pagina e fornire impaginazione per le tre pagine successive. Potete anche utilizzare questa implementazione per visualizzare un testo descrittivo come "43 risultati trovati" .
    • total=100 , more=true - Indica che il numero totale di hit è maggiore di 100 e il conteggio esatto non è noto. L’interfaccia utente può essere visualizzata fino a dieci nella prima pagina e fornire impaginazione per le dieci pagine successive. È inoltre possibile utilizzare questa opzione per visualizzare un testo come "più di 100 risultati trovati" . Man mano che l'utente passa alle pagine successive, le chiamate effettuate al Generatore di query aumentano il limite di guessTotal e anche dei offset parametri e limit .
guessTotal dovrebbe essere utilizzato anche nei casi in cui l'interfaccia utente deve utilizzare lo scorrimento infinito, per evitare che il Generatore di query determini l'esatto numero di hit.

Trovare i file JAR e ordinarli, per primi

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

Trovare tutte le pagine e ordinarle in base all'ultima modifica

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

Trova tutte le pagine e ordinale per ultima modifica, ma decrescente

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

Ricerca full-text, ordinata per punteggio

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

Ricerca di pagine con tag specifici

`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

Utilizzate il tagid predicate come nell'esempio se conoscete l'ID di tag esplicito.
Usate il tag predicato per il percorso del titolo del tag (senza spazi).
Poiché, nell'esempio precedente, state cercando pagine ( cq:Page nodi), è necessario utilizzare il percorso relativo da tale nodo per il tagid.property predicato, ovvero jcr:content/cq:tags . Per impostazione predefinita, tagid.property lo sarebbero semplicemente cq:tags .

Ricerca in più percorsi (tramite gruppi)

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

Questa query utilizza un gruppo (denominato " group ") che agisce per delimitare le sottoespressioni all'interno di una query, come accade per le parentesi in notazioni più standard. Ad esempio, la query precedente potrebbe essere espressa in uno stile più familiare come:
"Management" and ("/content/geometrixx/en/company/management" or "/content/geometrixx/en/company/bod")
All'interno del gruppo nell'esempio, il path predicato viene utilizzato più volte. Per distinguere e ordinare le due istanze del predicato (l'ordine è richiesto per alcuni predicati), è necessario preimpostare i predicati con N _ where *N *come indice di ordinamento. Nell'esempio precedente, i predicati risultanti sono 1_path e 2_path .
Il p punto p.or è un delimitatore speciale che indica che ciò che segue (in questo caso un or ) è un parametro del gruppo, invece di un subpredicato del gruppo, come 1_path .
Se non p.or viene fornito alcun predicato, tutti i predicati vengono inseriti insieme, ovvero ogni risultato deve soddisfare tutti i predicati.
Non è possibile utilizzare lo stesso prefisso numerico in una singola query, anche per diversi predicati.

Cerca proprietà

Qui state cercando tutte le pagine di un determinato modello, utilizzando la cq:template proprietà:
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

Questo ha lo svantaggio che i nodi jcr:content delle pagine, non le pagine stesse, vengono restituiti. Per risolvere questo problema, potete eseguire una ricerca in base al percorso 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

Ricerca di più proprietà

Quando si utilizza più volte il predicato delle proprietà, è necessario aggiungere di nuovo i prefissi numerici:
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

Ricerca di più valori di proprietà

Per evitare gruppi di grandi dimensioni quando si desidera cercare più valori di una proprietà ( "A" or "B" or "C" ), è possibile fornire più valori al property predicato:
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

Per le proprietà multivalore, potete anche richiedere che più valori corrispondano ( "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

Ottimizzazione dei risultati

Per impostazione predefinita, il servlet JSON QueryBuilder restituirà un set predefinito di proprietà per ciascun nodo nel risultato della ricerca (ad esempio percorso, nome, titolo, ecc.). Per controllare quali proprietà vengono restituite, è possibile effettuare una delle seguenti operazioni:
Specifica
p.hits=full

in tal caso tutte le proprietà saranno incluse per ciascun 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

Utilizzo
p.hits=selective

e specificare le proprietà in cui si desidera accedere
p.properties

separati da uno spazio:
http://localhost:4502/bin/querybuilder.json?p.hits=selective&property=jcr%3atitle&property.value=Triangle
property=jcr:title
property.value=Triangle
p.hits=selective
p.properties=sling:resourceType jcr:primaryType

È inoltre possibile includere nodi secondari nella risposta di QueryBuilder. A tal fine è necessario specificare
p.nodedepth=n

dove n è il numero di livelli che la query deve restituire. Per restituire un nodo figlio, è necessario specificarlo dal selettore delle proprietà
p.hits=full

Esempio:
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

Altri predici

Per ulteriori predicati, consultate la pagina Riferimento predicato di Query Builder.
È inoltre possibile controllare Javadoc per le . Javadoc per queste classi contiene l'elenco delle proprietà utilizzabili.
Il prefisso del nome della classe (ad esempio, " similar " in SimilarityPredicateEvaluator ) è la proprietà ** principal della classe. Questa proprietà è anche il nome del predicato da utilizzare nella query (in lettere minuscole).
Per tali proprietà principali, è possibile ridurre la query e utilizzare " similar=/content/en " invece della variante completa " similar.similar=/content/en ". Il modulo completo deve essere utilizzato per tutte le proprietà non principali di una classe.

Esempio di utilizzo dell'API Query Builder

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

Per informazioni su come creare un bundle OSGi che utilizza l’API QueryBuilder e utilizzare il bundle OSGi all’interno di un’applicazione Adobe Experience Manager, consultate Creazione di bundle Adobe CQ OSGi che utilizzano l’ API Query Builder.
La stessa query eseguita su HTTP tramite il servlet Query 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

Memorizzazione e caricamento delle query

Le query possono essere memorizzate nella directory archivio in modo da poterle utilizzare in un secondo momento. Il QueryBuilder metodo " storeQuery include la firma seguente:
void storeQuery(Query query, String path, boolean createFile, Session session) throws RepositoryException, IOException;

Quando si utilizza il QueryBuilder#storeQuery metodo, il dato Query viene memorizzato nell'archivio come file o come proprietà in base al valore dell' createFile argomento. L'esempio seguente mostra come salvare un percorso Query come /mypath/getfiles file:
builder.storeQuery(query, "/mypath/getfiles", true, session);

Eventuali query precedentemente archiviate possono essere caricate dall'archivio utilizzando il QueryBuilder#loadQuery metodo:
Query loadQuery(String path, Session session) throws RepositoryException, IOException

Ad esempio, un Query percorso memorizzato /mypath/getfiles può essere caricato dal seguente snippet:
Query loadedQuery = builder.loadQuery("/mypath/getfiles", session);

Test e debug

Per riprodurre e debuggare query querybuilder, è possibile utilizzare la console QueryBuilder Debugger in
http://localhost:4502/libs/cq/search/content/querydebug.html
oppure, in alternativa, il servlet json querybuilder su
http://localhost:4502/bin/querybuilder.json?path=/tmp
( path=/tmp è solo un esempio).

Raccomandazioni generali per il debug

Ottenete XPath spiegabile tramite la registrazione

Spiegare tutte le query durante il ciclo di sviluppo rispetto all'indice di destinazione impostato.
  • Abilitare i registri DEBUG per QueryBuilder per ottenere la query XPath sottostante spiegabile
    • Andate a https://<serveraddress>:<serverport>/system/console/slinglog. Create un nuovo logger per com.day.cq.search.impl.builder.QueryImpl in DEBUG .
  • Una volta attivato DEBUG per la classe sopra riportata, i registri visualizzeranno l'XPath generato da Query Builder.
  • Copiate la query XPath dalla voce di registro per la query QueryBuilder associata, ad esempio:
    • 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"))]
  • Incolla la query XPath in Spiega query come XPath per oscurare il piano di query

Ottenete XPath spiegabile tramite il debugger di Query Builder

  • Utilizzate il debugger di AEM QueryBuilder per generare una query XPath spiegabile:
Spiegare tutte le query durante il ciclo di sviluppo rispetto all'indice di destinazione impostato.
Ottenete XPath spiegabile tramite la registrazione
  • Abilitare i registri DEBUG per QueryBuilder per ottenere la query XPath sottostante spiegabile
    • Andate a https://<serveraddress>:<serverport>/system/console/slinglog. Create un nuovo logger per com.day.cq.search.impl.builder.QueryImpl in DEBUG .
  • Una volta attivato DEBUG per la classe sopra riportata, i registri visualizzeranno l'XPath generato da Query Builder.
  • Copiare la query XPath dalla voce di registro per la query QueryBuilder associata, ad esempio:
    • 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"))]
  • Incollare la query XPath in Spiega query come XPath per ottenere il piano di query
Ottenete XPath spiegabile tramite il debugger di Query Builder
  • Utilizzate il debugger di AEM QueryBuilder per generare una query XPath spiegabile:
  1. Fornisce la query Query Builder nel debugger di Query Builder
  2. Eseguire la ricerca
  3. Ottenete l'XPath generato
  4. Incollare la query XPath in Explain Query come XPath per ottenere il piano di query
Le query non-querybuilder (XPath, JCR-SQL2) possono essere fornite direttamente a Explain Query.
Per un elenco a discesa su come eseguire il debug delle query con QueryBuilder, vedete il video seguente.

Debug di query con registrazione

La configurazione dei logger è descritta nella sezione Creazione di Autori e Autori .
L'output di registro (livello INFO) dell'implementazione del generatore di query durante l'esecuzione della query descritta in Testing and Debugging:
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 si dispone di una query utilizzando i valutatori predicati che filtrano o utilizzano un ordine personalizzato per confronto, anche questo verrà notato nella query:
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