Site Search : Sites admin search (Settings > Sites) sorts alphabetically with no exact-match priority, burying exact Site Key matches on later pages
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Problem Statement
The Settings > Sites search box (view_hosts.jsp) matches the filter text against both Site Key and Aliases (case-insensitive substring match), but results are sorted purely alphabetically by hostname with no relevance ranking. An exact Site Key match can end up buried several pages behind unrelated sites whose aliases merely contain the search term as a substring, forcing the user to page through results to find it.
Steps to Reproduce
- Create a Site with key dotcms.com and no aliases.
- Create many other Sites whose aliases contain dotcms.com as a substring (e.g. app.dotcms.com, test.dotcms.com, staging.dotcms.com, etc.) — enough to span multiple result pages.
- Go to Settings > Sites.
- Type dotcms.com into the search box.
Expected Behavior
Since dotcms.com is an exact match on Site Key, it should be ranked at or near the top of the result set (or at minimum sorted ahead of sites that only match via a substring in their Aliases), independent of alphabetical position.
Actual Behavior
The exact Site Key match is sorted purely alphabetically alongside every alias-substring match, so it can land on an arbitrarily later results page depending on how many other sites alphabetically precede it. The user has to manually page through results to locate it.
Root Cause
File: dotCMS/src/main/java/com/dotmarketing/business/ajax/HostAjax.java
Method: findHostsPaginated (lines 124–188)
Both Site Key and Aliases are searched (confirmed by the method's own Javadoc, lines 105–108):
"When filtering results, only listed text-type fields can be searched, which are basically the two columns displayed in the UI: Site Key, and Aliases."
The actual match logic is a case-insensitive substring check with no distinction between an exact key match and a partial alias match (lines 143–151):
for (final Field searchableField : searchableFields) {
final String value = site.getStringProperty(searchableField.getVelocityVarName());
if (UtilMethods.isSet(value) && value.toLowerCase().contains(filter.toLowerCase())) {
addToResultList = true;
break;
}
}
Sorting is alphabetical only, applied before filtering, with no relevance boost (line 137):
sitesFromDb.sort(new HostNameComparator());
File: dotCMS/src/main/java/com/dotmarketing/business/util/HostNameComparator.java (lines 7–15):
public class HostNameComparator implements Comparator<Host> {
public int compare(Host o1, Host o2) {
String host1 = o1.getHostname().toUpperCase();
String host2 = o2.getHostname().toUpperCase();
return host1.compareTo(host2);
}
}
Pagination is sliced from the sorted, filtered list (lines 180–188), so the alphabetical-only order directly determines which page an exact match lands on:
final long totalResults = siteList.size();
// Paginate results only if required
if (totalResults > count) {
if (totalResults > 0 && count > 0) {
offset = offset >= siteList.size() ? siteList.size() - 1 : offset;
count = offset + count > siteList.size() ? siteList.size() : offset + count;
siteList = siteList.subList(offset, count);
}
}
Frontend call path — the JSP search box invokes this DWR method directly:
File: dotCMS/src/main/webapp/html/portlet/ext/hostadmin/view_hosts.jsp (lines 51–57) — search input (id="filter"), Reset button, and "Show Archived" checkbox (id="showDeleted").
File: dotCMS/src/main/webapp/html/portlet/ext/hostadmin/view_hosts_js_inc.jsp (line 362):
refreshHostTable: function(){
var filter = dijit.byId('filter').attr('value');
var showDeleted = dijit.byId('showDeleted').attr('checked');
var offset = (this.currentPage - 1) * this.RESULTS_PER_PAGE;
var count = this.RESULTS_PER_PAGE;
HostAjax.findHostsPaginated(filter, showDeleted, offset, count, dojo.hitch(this, this.refreshHostTableCallback));
}
Existing Precedent for the Fix
dotCMS already implements exact-match prioritization elsewhere, for the newer Site Selector endpoint (/api/v1/site), just not on this admin screen:
File: dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java (lines 148–150):
// query that Exact matches should be at the top of the search results.
private static final String PRIORITIZE_EXACT_MATCHES =
" ORDER BY length(%s), %s ";
Applied at line 989:
sqlQuery.append(getSiteNameOrAliasColumn(PRIORITIZE_EXACT_MATCHES, true, "c", "c"));
This ORDER BY length(column), column pattern sorts shorter (more exact) matches first, then alphabetically — exactly the behavior missing from HostAjax.findHostsPaginated.
Suggested Fix
In HostAjax.findHostsPaginated, replace or supplement the HostNameComparator sort with a comparator that ranks exact Site Key matches (and ideally exact alias matches) above substring matches, before the pagination slice is applied — mirroring the PRIORITIZE_EXACT_MATCHES pattern already proven in HostFactoryImpl. This should apply only when a filter is present (unfiltered listing should presumably keep pure alphabetical order).
Acceptance Criteria
- When a search filter is entered and one or more Sites have a Site Key that exactly matches the filter (case-insensitive), those Sites appear on the first page of results.
- Relative ordering among non-exact matches is unchanged (still alphabetical).
- Unfiltered "Show Archived" / default listing behaviour is unaffected.
- Existing pagination (offset/count) continues to work correctly against the newly ordered list.
- Add/update a unit test around HostAjax.findHostsPaginated (or an extracted sorting helper) covering the exact-match-vs-alias-substring-match scenario described above.
dotCMS Version
latest evergreen
Severity
High - Major functionality broken
Links
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in dotCMS/src/main/java/com/dotmarketing/business/ajax/HostAjax.java at findHostsPaginated, then compare its sorting and filtering with HostNameComparator.java and the PRIORITIZE_EXACT_MATCHES precedent in HostFactoryImpl.java. Trace the call from view_hosts_js_inc.jsp, add or update a test for exact Site Key versus alias-substring results, and verify first-page priority, unchanged non-exact ordering, unfiltered behavior, and pagination.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, javascript
- Domain
- backend, search
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100