Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
BedrockMission!

Learn More

View all

Sign in to view all badges

using QueryBuilder how to get the absolute URLs of the pages of the components found?

Avatar

Avatar
Validate 10
Level 4
TB3dock
Level 4

Likes

23 likes

Total Posts

153 posts

Correct Reply

4 solutions
Top badges earned
Validate 10
Validate 1
Ignite 5
Ignite 3
Ignite 1
View profile

Avatar
Validate 10
Level 4
TB3dock
Level 4

Likes

23 likes

Total Posts

153 posts

Correct Reply

4 solutions
Top badges earned
Validate 10
Validate 1
Ignite 5
Ignite 3
Ignite 1
View profile
TB3dock
Level 4

21-04-2021

Using QueryBuilder we can search for component(s) which contain a property with a specific value (e.g. an ID we are looking for).   From this, I need to return some json which includes the properties of the component, the absolute URL of the page this component is on, and the values of some other specific components on the same page, for each hit.  E.g. if we have a bunch of game info pages, each having a game info block component which has gameId as a field, I need to search for specific games (e.g. from a list of previously played game ids), and return the URLS of the game pages found, along with all the main block and other block properties as json so it can be rendered on client side using react.  Below is some code which gets the properties of each game block.

Q1: How to get the absolute URL of the page the block is on or the other components on the page?

Q2: how to improve the search time by narrowing down the predicate?  Eg. how to find published only, and only for the required component type or page template type?

Q3: is there a better way than lots of hand manipulation, e.g. can something like sling model exporters be used?

Q4: I tried to do gson.toJson(searchResult), so I can see what data it holds, but this fails due to duplicate fields.  Is there another way to dump the entire searchResult so we can figure out whats in it, rather than manually printing every value in various loops? I am using eclipse, but haven't seen anything on getting cloud SDK to work in debugger so the vars can be inspected.

 

 

	predicate.put("path", "/content/ourweb/en/");
	predicate.put("type", "cq:component");
	predicate.put("property", "ourId");
	predicate.put("property.value", "1234");
		
	Query query = builder.createQuery(PredicateGroup.create(predicate), session);
	SearchResult searchResult = query.getResult();	
	Gson gson = new GsonBuilder().setPrettyPrinting().create();
	String result = "";
	for(Hit hit : searchResult.getHits()) {
		String path = hit.getPath();		
		result += " hits: " + gson.toJson(hit.getProperties());
	}

 

 

There was a great reply, but it seems to have been deleted.

It had this in it:

            final Resource hitResource = hit.getResource();
if (hitResource != null) {
final Page page = getPage(hitResource);
if (page != null) {
final Resource contentResource = page.getContentResource();
getResultList(resourceResolver, searchResultsLists, hit, hitResource, contentResource);
}

 getPage looks useful, is this a built in function? 

what does page.get|ContentResource() return  exaclty?

Accepted Solutions (1)

Accepted Solutions (1)

Avatar

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile
asutosh_jena
Level 10

21-04-2021

Hi @TB3dock 

 

Reposting my answers here:

First you can make a VO or POJO class with all the required fields. Let's say I want to keep page title and page link for now. You can add all the fields that you want.

 

public class SearchResultsList {

private String pageTitle;
private String pageLink;

public String getPageTitle() {
return pageTitle;
}

public void setPageTitle(String pageTitle) {
this.pageTitle = pageTitle;
}

public String getPageLink() {
return pageLink;
}

public void setPageLink(String pageLink) {
this.pageLink = pageLink;
}

@Override
public String toString() {
return "SearchResultsList{" +
"pageTitle='" + pageTitle + '\'' +
", pageLink='" + pageLink + '\'' +
'}';
}
}

 

You can create a search service and write the required logic to search here. I am not adding the details here. Predicates and all will go here.

Now call the search service and then get the results.

final SearchResult searchResults = searchService.getSearchResults(resourceResolver, searchRootPath); // whatever you want here can be performed inside the service

 

Once you have the search result preapre the desired result by parsing the raw search result:

 

private List<SearchResultsList> parseResults(SearchResult searchResult, ResourceResolver resourceResolver) {
List<SearchResultsList> searchResultsLists = new ArrayList<>();
totalResult = searchResult.getTotalMatches();
final List<Hit> hits = searchResult.getHits();
try {
for (Hit hit : hits) {
final Resource hitResource = hit.getResource();
if (hitResource != null) {
final Page page = getPage(hitResource);
if (page != null) {
final Resource contentResource = page.getContentResource();
getResultList(resourceResolver, searchResultsLists, hit, hitResource, contentResource);
}
}
}
} catch (RepositoryException e) {
log.error("***** :: parseResult :: Exception *****", e);
}
return searchResultsLists;
}

 

private void getResultList(ResourceResolver resourceResolver, List<SearchResultsList> searchResultsLists, Hit hit, Resource hitResource, Resource contentResource) throws RepositoryException {
if (contentResource != null) {
final ValueMap pageValueMap = contentResource.getValueMap(); // This will give the page property

SearchResultsList searchResultsList = new SearchResultsList();
final String pageTitle = pageValueMap.get(NameConstants.PN_PAGE_TITLE) != null ? pageValueMap.get(NameConstants.PN_PAGE_TITLE).toString() : pageValueMap.get(NameConstants.PN_TITLE).toString();
searchResultsList.setPageTitle(pageTitle);
searchResultsList.setPageLink(StringUtils.isNotBlank(hitResource.getPath()) ? LinksUtil.checkInternalURLByPath(hitResource.getPath(), resourceResolver) : StringUtils.EMPTY); // This will give the page path or link
// rest all can be added here whatever you have in the POJO class.

searchResultsLists.add(searchResultsList);
}
}
private Page getPage(Resource resource) {
if (resource != null) {
ResourceResolver resourceResolver = resource.getResourceResolver();
PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
if (pageManager != null) {
return pageManager.getContainingPage(resource);
}
}
return null;
}

Once you have the list you can convert the list into JSON using Gson and then use it wherever you want.

 

Gson gson = new Gson();
String jsonString = gson.toJson(searchResultsLists); // This will return JSON response of the POJO or VO.

 

Answers (3)

Answers (3)

Avatar

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile
asutosh_jena
Level 10

21-04-2021

Hi @TB3dock 

 

getPage(resource)

was missing in my response and I have added it back now. It's a custom method that was written.

 

getContentResource() returns the addressed resource of the page's content or null if the respective resource does not exist. It's nothing but just the jcr:content node as a resource which will be adapted into ValueMap.

 

Thanks!

Avatar

Avatar
Validate 10
Level 4
TB3dock
Level 4

Likes

23 likes

Total Posts

153 posts

Correct Reply

4 solutions
Top badges earned
Validate 10
Validate 1
Ignite 5
Ignite 3
Ignite 1
View profile

Avatar
Validate 10
Level 4
TB3dock
Level 4

Likes

23 likes

Total Posts

153 posts

Correct Reply

4 solutions
Top badges earned
Validate 10
Validate 1
Ignite 5
Ignite 3
Ignite 1
View profile
TB3dock
Level 4

21-04-2021

Below is the response from asutosh_jena which seems to have disappeared from this thread.

 

First you can make a VO or POJO class with all the required fields. Let's say I want to keep page title and page link for now. You can add all the fields that you want.

 

public class SearchResultsList {

private String pageTitle;
private String pageLink;

public String getPageTitle() {
return pageTitle;
}

public void setPageTitle(String pageTitle) {
this.pageTitle = pageTitle;
}

public String getPageLink() {
return pageLink;
}

public void setPageLink(String pageLink) {
this.pageLink = pageLink;
}

@Override
public String toString() {
return "SearchResultsList{" +
"pageTitle='" + pageTitle + '\'' +
", pageLink='" + pageLink + '\'' +
'}';
}
}

 

You can create a search service and write the required logic to search here. I am not adding the details here. Predicates and all will go here.

Now call the search service and then get the results.

final SearchResult searchResults = searchService.getSearchResults(resourceResolver, searchRootPath); // whatever you want here can be performed inside the service

 

Once you have the search result preapre the desired result by parsing the raw search result:

 

private List<SearchResultsList> parseResults(SearchResult searchResult, ResourceResolver resourceResolver) {
List<SearchResultsList> searchResultsLists = new ArrayList<>();
totalResult = searchResult.getTotalMatches();
final List<Hit> hits = searchResult.getHits();
try {
for (Hit hit : hits) {
final Resource hitResource = hit.getResource();
if (hitResource != null) {
final Page page = getPage(hitResource);
if (page != null) {
final Resource contentResource = page.getContentResource();
getResultList(resourceResolver, searchResultsLists, hit, hitResource, contentResource);
}
}
}
} catch (RepositoryException e) {
log.error("***** :: parseResult :: Exception *****", e);
}
return searchResultsLists;
}

 

private void getResultList(ResourceResolver resourceResolver, List<SearchResultsList> searchResultsLists, Hit hit, Resource hitResource, Resource contentResource) throws RepositoryException {
if (contentResource != null) {
final ValueMap pageValueMap = contentResource.getValueMap(); // This will give the page property

SearchResultsList searchResultsList = new SearchResultsList();
final String pageTitle = pageValueMap.get(NameConstants.PN_PAGE_TITLE) != null ? pageValueMap.get(NameConstants.PN_PAGE_TITLE).toString() : pageValueMap.get(NameConstants.PN_TITLE).toString();
searchResultsList.setPageTitle(pageTitle);
searchResultsList.setPageLink(StringUtils.isNotBlank(hitResource.getPath()) ? LinksUtil.checkInternalURLByPath(hitResource.getPath(), resourceResolver) : StringUtils.EMPTY); // This will give the page path or link
// rest all can be added here whatever you have in the POJO class.

searchResultsLists.add(searchResultsList);
}
}

 

Once you have the list you can convert the list into JSON using Gson and then use it wherever you want.

 

Gson gson = new Gson();
String jsonString = gson.toJson(searchResultsLists); // This will return JSON response of the POJO or VO.

 

Avatar

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile

Avatar
Affirm 100
Level 10
asutosh_jena
Level 10

Likes

367 likes

Total Posts

462 posts

Correct Reply

134 solutions
Top badges earned
Affirm 100
Ignite 1
Establish
Give Back 50
Give Back 5
View profile
asutosh_jena
Level 10

21-04-2021

Hi @TB3dock 

 

First you can make a VO or POJO class with all the required fields. Let's say I want to keep page title and page link for now. You can add all the fields that you want.

 

public class SearchResultsList {

private String pageTitle;
private String pageLink;

public String getPageTitle() {
return pageTitle;
}

public void setPageTitle(String pageTitle) {
this.pageTitle = pageTitle;
}

public String getPageLink() {
return pageLink;
}

public void setPageLink(String pageLink) {
this.pageLink = pageLink;
}

@Override
public String toString() {
return "SearchResultsList{" +
"pageTitle='" + pageTitle + '\'' +
", pageLink='" + pageLink + '\'' +
'}';
}
}

 

You can create a search service and write the required logic to search here. I am not adding the details here. Predicates and all will go here.

Now call the search service and then get the results.

final SearchResult searchResults = searchService.getSearchResults(resourceResolver, searchRootPath); // whatever you want here can be performed inside the service

 

Once you have the search result preapre the desired result by parsing the raw search result:

 

private List<SearchResultsList> parseResults(SearchResult searchResult, ResourceResolver resourceResolver) {
List<SearchResultsList> searchResultsLists = new ArrayList<>();
totalResult = searchResult.getTotalMatches();
final List<Hit> hits = searchResult.getHits();
try {
for (Hit hit : hits) {
final Resource hitResource = hit.getResource();
if (hitResource != null) {
final Page page = getPage(hitResource);
if (page != null) {
final Resource contentResource = page.getContentResource();
getResultList(resourceResolver, searchResultsLists, hit, hitResource, contentResource);
}
}
}
} catch (RepositoryException e) {
log.error("***** :: parseResult :: Exception *****", e);
}
return searchResultsLists;
}

 

private void getResultList(ResourceResolver resourceResolver, List<SearchResultsList> searchResultsLists, Hit hit, Resource hitResource, Resource contentResource) throws RepositoryException {
if (contentResource != null) {
final ValueMap pageValueMap = contentResource.getValueMap(); // This will give the page property

SearchResultsList searchResultsList = new SearchResultsList();
final String pageTitle = pageValueMap.get(NameConstants.PN_PAGE_TITLE) != null ? pageValueMap.get(NameConstants.PN_PAGE_TITLE).toString() : pageValueMap.get(NameConstants.PN_TITLE).toString();
searchResultsList.setPageTitle(pageTitle);
searchResultsList.setPageLink(StringUtils.isNotBlank(hitResource.getPath()) ? LinksUtil.checkInternalURLByPath(hitResource.getPath(), resourceResolver) : StringUtils.EMPTY); // This will give the page path or link
// rest all can be added here whatever you have in the POJO class.

searchResultsLists.add(searchResultsList);
}
}

 

Once you have the list you can convert the list into JSON using Gson and then use it wherever you want.

 

Gson gson = new Gson();
String jsonString = gson.toJson(searchResultsLists); // This will return JSON response of the POJO or VO.

 

Hope this helps!

Thanks