Last updatedSep 10, 2019

Rate this page:

Create a search decorator

Applicable:This tutorial applies to Confluence 7.0 or higher.
Level of experience:Advanced. You should complete at least one intermediate tutorial before working through this tutorial.

This tutorial demonstrates how to change the behaviour of the default v2 search. As the v2 search API is the ubiquitous way to access search, the search decorator affects all Confluence functionality that relies on search. You can use it to change the order of contents returned by search, or change the filter to exclude a certain type of content.

In this tutorial we will change the search behaviour to always boost content created by the currently logged in user.

Before you begin

To complete this tutorial, you'll need to be familiar with:

Source code

You can find the source code for this tutorial on Atlassian Bitbucket.

To clone the repository, run the following command:

1
git clone https://bitbucket.org/atlassian_tutorial/confluence-v2-search-decorator-tutorial.git

Alternatively, you can download the source as a ZIP archive.

This tutorial was last tested with Confluence 7.0 using the Atlassian SDK 8.0.2.

Step 1: Implement the SearchDecorator interface

The PromoteContentCreatorSearchDecorator is a plugin module that implements the SearchDecorator interface. It has a single method, SearchDecorator#decorate. This method takes an original ISearch object and returns another ISearch object that behaves differently. The UserManager is injected into the constructor of the class that will be used to obtain the UserKey of the logged in user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PromoteContentCreatorSearchDecorator implements SearchDecorator {
    private final UserManager userManager;
 
    @Autowired
    public PromoteContentCreatorSearchDecorator(@ComponentImport UserManager userManager) {
        this.userManager = requireNonNull(userManager);
    }
 
    @Override
    public ISearch decorate(ISearch search) {
        UserKey loginUserKey = userManager.getRemoteUserKey();
        if (loginUserKey != null) {
            return new PromoteContentCreatorSearch(search, loginUserKey);
        }
        return search;
    }
    ...

Step 2: Change the query to promote content created by the logged in user

The PromoteContentCreatorSearch is a wrapper around the original ISearch object with the key of login user. It overrides the ISearch#getQuery method to return a different query. The query has the effect of boosting content created by the currently logged in user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static class PromoteContentCreatorSearch implements ISearch {
    private final ISearch delegate;
    private final UserKey creator;
 
    private PromoteContentCreatorSearch(ISearch delegate, UserKey creator) {
        this.delegate = delegate;
        this.creator = creator;
    }
 
    @Override
    public SearchQuery getQuery() {
        // a content matching should clause adds an overwhelming contribution to the overall score so it
        // is ranked before any unmatched content
        return BooleanQuery.builder()
                .addMust(delegate.getQuery())
                .addShould(new ConstantScoreQuery(new CreatorQuery(creator), 50.0f))
                .build();
    }
    ...

Step 3: Make it visible to Confluence

Here is an example atlassian-plugin.xml file containing a search decorator:

1
2
3
4
5
...
<search-decorator key="promoteContentCreatorSearchDecorator"
                      class="com.atlassian.confluence.plugins.v2.search.tutorial.PromoteContentCreatorSearchDecorator"
                      weight="100"/>
...

Step 4: See how it works

Start a local Confluence instance

  1. Make sure you have saved all your code changes to this point.

  2. Open a Terminal and navigate to the plugin root folder (where the pom.xml file is stored).

  3. Run the following command:

    1
    atlas-run

    This command builds your plugin code, starts a Confluence instance, and installs your plugin. This may take a while. When the process is complete, you’ll see many status lines on your screen concluding with something like this:

    1
    2
    3
    [INFO] Confluence started successfully in 71s at http://localhost:1990/confluence
    [INFO] Type CTRL-D to shutdown gracefully
    [INFO] Type CTRL-C to exit
  4. In your browser, go to your local Confluence instance at http://localhost:1990/confluence and log in as admin / admin

  5. Create a page with title "decorate confluence search".

You can also build the plugin and deploy it into an existing Confluence instance.

Explain a query

Use explain.action to check the content is being boosted as expected.

  1. In your browser, enter http://localhost:1990/confluence/explain.action?queryString=confluence

  2. Verify that the page with title "decorate confluence search" appears on the top, and check the contribution of subquery "ConstantScoreQuery(new CreatorQuery(creator), 50.0f)" in the overall score.

Screenshot: Explain query output in browser

Next steps

Learn more about extending Confluence's search capabilities with these tutorials:

Rate this page: