| The REST keyword-search endpoints accept a repeatable "scope" query parameter that selects what to search in (content, name, title, spaces, objects):
When a client repeats the same scope value (e.g. scope=content&scope=content, or sends the same scope twice by mistake), the duplicate is meant to be dropped: BaseSearchResult.parseSearchScopeStrings() has a guard whose whole purpose is to skip a scope that was already added. That guard never fires. Root cause: the guard compares the wrong types. searchScopes is a List<KeywordSearchScope> but the value tested is the raw String scope name, so "searchScopes.contains(searchScopeString)" is always false and no scope is ever recognised as a duplicate. What a user hits: When duplicate scopes are passed, they are carried through unchanged instead of being collapsed. Downstream, DatabaseKeywordSearchSource builds the HQL WHERE clause by OR-ing one predicate per scope in the list, so a duplicated page scope produces a redundant, repeated predicate, e.g.:
The database therefore executes a needlessly larger query for the same result set. Result rows themselves are not duplicated in practice (the page query uses "select distinct", and the spaces/objects scopes are guarded with contains()), so this is a query-efficiency / broken-contract bug rather than a wrong-results bug. Steps to reproduce: 1. On any XWiki instance, call: GET /xwiki/rest/wikis/xwiki/search?q=test&scope=content&scope=content 2. Inspect the generated HQL (query logging, or DatabaseKeywordSearchSource). Expected: the two identical "content" scopes are collapsed to a single predicate. Actual: the content predicate appears twice, OR-ed together. |