Find All Documents That Link to a Specific Document
Overview
This page describes how to create and execute a search query to find all documents that contain a link to a specific document in Bloomreach Content.
When to Use
Use this approach when you need to retrieve all documents that reference a particular document. A common scenario is displaying all comments associated with an article, where each comment is a separate document linked to the article.
Technical Background
In Bloomreach Content, you create relationships between documents by linking them. At the content repository level, these links are represented by nodes of type hippo:mirror or hippo:facetselect (or their subtypes).
For example, to relate a comment to an article, the comment document includes a child node of type hippo:mirror. The hippo:docbase property of this node stores the UUID of the handle node of the target document.
The following structure illustrates this relationship:
/content: /documents: /news: /2012: /my-news-article: jcr:primaryType: hippo:handle jcr:uuid: xxxx-xxxx-xxxx-xxxx /my-news-article: jcr:primaryType: hippo:document /comments: /2012: /my-news-article: jcr:primaryType: hippostd:folder /comment-1: /hippo:mirror: hippo:docbase: xxxx-xxxx-xxxx-xxxx /comment-2: /hippo:mirror: hippo:docbase: xxxx-xxxx-xxxx-xxxx
In this example:
- The
my-news-articledocument has a handle node with UUIDxxxx-xxxx-xxxx-xxxx. - Two comments (
comment-1andcomment-2) each have ahippo:mirrorchild node with ahippo:docbaseproperty referencing the article's UUID. - This structure allows you to query for all comments linked to
my-news-articleby searching for documents with ahippo:mirrornode whosehippo:docbasematches the article's UUID.
The HST API provides the ContentBeanUtils class, which includes methods such as createIncomingBeansQuery to simplify these queries.
Implementation
Example 1: Retrieve the 10 Most Recent Comments on a News Article
The following example demonstrates how to query for the 10 most recent comments linked to a news article.
@Override public void doBeforeRender(HstRequest request, HstResponse response) throws HstComponentException { final HstRequestContext context = request.getRequestContext(); // Expect a NewsDocument in a news detail component NewsDocument newsDocument = context.getContentBean(NewsDocument.class); if (newsDocument == null) { response.setStatus(HstResponse.SC_NOT_FOUND); return; } // Set the newsDocument on the request request.setAttribute("document", newsDocument); // Query for the 10 most recent comments try { // Create a HstQuery to find CommentBean documents that: // 1. Have a hippo:mirror link at 'example:commentlink' // 2. The link points to 'newsDocument' // 3. Are located below the site content base HstQuery commentsQuery = ContentBeanUtils.createIncomingBeansQuery( newsDocument, context.getSiteContentBaseBean(), "example:commentlink/@hippo:docbase", CommentBean.class, false); // Order by date descending commentsQuery.addOrderByDescending("example:date"); // Limit to 10 results commentsQuery.setLimit(10); // Execute the query and add the result to the request HstQueryResult comments = commentsQuery.execute(); request.setAttribute("comments", comments); } catch (QueryException e) { log.warn("QueryException ", e); } }
To render the comments, iterate over the results using a HippoBeanIterator from HstQueryResult#getHippoBeans().
Example 2: Add Constraints to the Comment Query
You can add additional constraints to the HstQuery returned by createIncomingBeansQuery using the Legacy Search API. Note that you cannot use the Fluent Search API for queries created this way.
The following example restricts the query to comments made in the last year and containing a specific search string:
@Override public void doBeforeRender(HstRequest request, HstResponse response) throws HstComponentException { final HstRequestContext context = request.getRequestContext(); // Expect a NewsDocument in a news detail component NewsDocument newsDocument = context.getContentBean(NewsDocument.class); if(newsDocument == null) { response.setStatus(HstResponse.SC_NOT_FOUND); return; } // Set the newsDocument on the request request.setAttribute("document", newsDocument); // Query for the 10 most recent comments try { // Create a HstQuery as in the previous example HstQuery commentsQuery = ContentBeanUtils.createIncomingBeansQuery( newsDocument, context.getSiteContentBaseBean(), "example:commentlink/@hippo:docbase", CommentBean.class, false); // Order by date descending commentsQuery.addOrderByDescending("example:date"); // Limit to 10 results commentsQuery.setLimit(10); Filter extraFilter = commentsQuery.createFilter(); // Filter for comments since last year Calendar sinceLastYear = Calendar.getInstance(); sinceLastYear.add(Calendar.YEAR, -1); extraFilter.addGreaterOrEqualThan("example:date", sinceLastYear); // Add a free text search constraint String query = SearchInputParsingUtils.parse(..., false); extraFilter.addContains(".", query); // Combine the extra filter with the main filter ((Filter) commentsQuery.getFilter()).addAndFilter(extraFilter); // Execute the query and add the result to the request HstQueryResult comments = commentsQuery.execute(); request.setAttribute("comments", comments); } catch (QueryException e) { log.warn("QueryException ", e); } }
Render the results as in the previous example using a HippoBeanIterator.
Broader Queries with Wildcards and Depth
If you do not know the exact path where links are stored in the documents, you can use wildcard link paths or specify a search depth. For example, to find all instances of HippoDocument that link to your document, regardless of the link's location, use one of the following approaches:
- Specify wildcard paths such as
"*/@hippo:docbase"or"*/*/@hippo:docbase". - Provide a list of possible link paths, for example:
{"*/@hippo:docbase", "*/*/@hippo:docbase"}. - Use the
depthparameter to automatically include all link paths up to the specified depth.
The following table shows the correspondence between depth and link paths:
| Depth | Link Paths |
|---|---|
| 1 | {"*/@hippo:docbase"} |
| 2 | {"/@hippo:docbase", "/*/@hippo:docbase"} |
| 3 | {"/@hippo:docbase", "//@hippo:docbase", "///@hippo:docbase"} |
| 4 | {"/@hippo:docbase", "//@hippo:docbase", "///@hippo:docbase", "////@hippo:docbase"} |
To use depth in your query:
// Using depth = 2 finds incoming beans with links at "*/@hippo:docbase" or "*/*/@hippo:docbase" int depth = 2; HstQuery commentsQuery = ContentBeanUtils.createIncomingBeansQuery( newsDocument, context.getSiteContentBaseBean(), depth, HippoDocument.class, false);
Related Topics
- Legacy Search API
- Fluent Search API (not compatible with queries created by
createIncomingBeansQuery) - ContentBeanUtils JavaDoc
Summary
To find all documents that link to a specific document, use the ContentBeanUtils.createIncomingBeansQuery method. Adjust the query parameters, constraints, and link paths as needed for your use case. Use search depth or wildcard paths when the link location varies.