Skip to content
Snippets Groups Projects
Commit 4e26d8c7 authored by Marius Dumitru Florea's avatar Marius Dumitru Florea
Browse files

XWIKI-11513: Solr Query API searches by default only in technical documents

* Move the code that sets the xwiki.supportedLocales Solr query parameter from Main.SolrSearch and SOLRSearchSource to SolrQueryExecutor so that we don't have to duplicate it everywhere.
parent 13f616f9
No related merge requests found
Showing with 90 additions and 75 deletions
...@@ -52,5 +52,24 @@ ...@@ -52,5 +52,24 @@
<artifactId>xwiki-platform-search-solr-api</artifactId> <artifactId>xwiki-platform-search-solr-api</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<!-- Used to access the list of supported locales from the configuration of the current wiki. -->
<groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-oldcore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<!-- Required for MockitoOldcoreRule. -->
<groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-oldcore</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocument;
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
import org.slf4j.Logger; import org.slf4j.Logger;
import org.xwiki.bridge.DocumentAccessBridge; import org.xwiki.bridge.DocumentAccessBridge;
import org.xwiki.component.annotation.Component; import org.xwiki.component.annotation.Component;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.DocumentReference;
import org.xwiki.query.Query; import org.xwiki.query.Query;
import org.xwiki.query.QueryException; import org.xwiki.query.QueryException;
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
import org.xwiki.search.solr.internal.api.FieldUtils; import org.xwiki.search.solr.internal.api.FieldUtils;
import org.xwiki.search.solr.internal.api.SolrInstance; import org.xwiki.search.solr.internal.api.SolrInstance;
import com.xpn.xwiki.XWikiContext;
/** /**
* Executes Solr queries. * Executes Solr queries.
* <p/> * <p/>
...@@ -64,6 +66,12 @@ public class SolrQueryExecutor implements QueryExecutor ...@@ -64,6 +66,12 @@ public class SolrQueryExecutor implements QueryExecutor
*/ */
public static final String SOLR = "solr"; public static final String SOLR = "solr";
/**
* The parameter that specifies the list of supported locales. This is used to add generic (unlocalized) aliases for
* localized query fields (e.g. 'title' alias for 'title_en' query field).
*/
private static final String PARAM_SUPPORTED_LOCALES = "xwiki.supportedLocales";
/** /**
* Logging framework. * Logging framework.
*/ */
...@@ -77,49 +85,23 @@ public class SolrQueryExecutor implements QueryExecutor ...@@ -77,49 +85,23 @@ public class SolrQueryExecutor implements QueryExecutor
protected DocumentAccessBridge documentAccessBridge; protected DocumentAccessBridge documentAccessBridge;
/** /**
* Used to retrieve user preference regarding hidden documents. * Provider for the {@link SolrInstance} that allows communication with the Solr server.
*/ */
@Inject @Inject
@Named("user") protected Provider<SolrInstance> solrInstanceProvider;
protected ConfigurationSource userPreferencesSource;
/** /**
* Provider for the {@link SolrInstance} that allows communication with the Solr server. * Used to retrieve the configured supported locales.
*/ */
@Inject @Inject
protected Provider<SolrInstance> solrInstanceProvider; private Provider<XWikiContext> xcontextProvider;
@Override @Override
public <T> List<T> execute(Query query) throws QueryException public <T> List<T> execute(Query query) throws QueryException
{ {
try { try {
SolrInstance solrInstance = solrInstanceProvider.get(); SolrInstance solrInstance = solrInstanceProvider.get();
SolrQuery solrQuery = createSolrQuery(query);
SolrQuery solrQuery = new SolrQuery(query.getStatement());
// Overwrite offset and limit only if the query object explicitly says so, otherwise use whatever the query
// statement says or the defaults
if (query.getOffset() > 0) {
solrQuery.setStart(query.getOffset());
}
if (query.getLimit() > 0) {
solrQuery.setRows(query.getLimit());
}
// TODO: good idea? Any confusion? Do we really needs something like this?
// Reuse the Query.getNamedParameters() map to get extra parameters.
for (Entry<String, Object> entry : query.getNamedParameters().entrySet()) {
Object value = entry.getValue();
if (value instanceof Iterable) {
solrQuery.set(entry.getKey(), toStringArray((Iterable) value));
} else if (value != null && value.getClass().isArray()) {
solrQuery.set(entry.getKey(), toStringArray(value));
} else {
solrQuery.set(entry.getKey(), String.valueOf(value));
}
}
QueryResponse response = solrInstance.query(solrQuery); QueryResponse response = solrInstance.query(solrQuery);
// Check access rights need to be checked before returning the response. // Check access rights need to be checked before returning the response.
...@@ -137,6 +119,45 @@ public <T> List<T> execute(Query query) throws QueryException ...@@ -137,6 +119,45 @@ public <T> List<T> execute(Query query) throws QueryException
} }
} }
private SolrQuery createSolrQuery(Query query)
{
SolrQuery solrQuery = new SolrQuery(query.getStatement());
// Overwrite offset and limit only if the query object explicitly says so, otherwise use whatever the query
// statement says or the defaults.
if (query.getOffset() > 0) {
solrQuery.setStart(query.getOffset());
}
if (query.getLimit() > 0) {
solrQuery.setRows(query.getLimit());
}
// TODO: good idea? Any confusion? Do we really needs something like this?
// Reuse the Query.getNamedParameters() map to get extra parameters.
for (Entry<String, Object> entry : query.getNamedParameters().entrySet()) {
Object value = entry.getValue();
if (value instanceof Iterable) {
solrQuery.set(entry.getKey(), toStringArray((Iterable) value));
} else if (value != null && value.getClass().isArray()) {
solrQuery.set(entry.getKey(), toStringArray(value));
} else {
solrQuery.set(entry.getKey(), String.valueOf(value));
}
}
// Make sure the list of supported locales is set so the names of the fields that are indexed in multiple
// languages are expanded in the search query. For instance, the query "title:text" will be expanded to
// "title__:text OR title_en:text OR title_fr:text" if the list of supported locales is [en, fr].
if (!solrQuery.getParameterNames().contains(PARAM_SUPPORTED_LOCALES)) {
XWikiContext xcontext = this.xcontextProvider.get();
solrQuery.set(PARAM_SUPPORTED_LOCALES,
StringUtils.join(xcontext.getWiki().getAvailableLocales(xcontext), ","));
}
return solrQuery;
}
/** /**
* Converts an arbitrary array to an array containing its string representations. * Converts an arbitrary array to an array containing its string representations.
* *
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale;
import javax.inject.Provider; import javax.inject.Provider;
...@@ -44,9 +45,11 @@ ...@@ -44,9 +45,11 @@
import org.xwiki.test.annotation.ComponentList; import org.xwiki.test.annotation.ComponentList;
import org.xwiki.test.mockito.MockitoComponentMockingRule; import org.xwiki.test.mockito.MockitoComponentMockingRule;
import static org.mockito.Matchers.any; import com.xpn.xwiki.XWikiContext;
import static org.mockito.Mockito.mock; import com.xpn.xwiki.test.MockitoOldcoreRule;
import static org.mockito.Mockito.when;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
/** /**
* Basic test for the {@link SolrQueryExecutor}. * Basic test for the {@link SolrQueryExecutor}.
...@@ -56,10 +59,9 @@ ...@@ -56,10 +59,9 @@
@ComponentList({DefaultQueryManager.class, DefaultQueryExecutorManager.class, ContextComponentManagerProvider.class}) @ComponentList({DefaultQueryManager.class, DefaultQueryExecutorManager.class, ContextComponentManagerProvider.class})
public class SolrQueryExecutorTest public class SolrQueryExecutorTest
{ {
private static final String ITERABLE_PARAM_NAME = "multiParam"; private static final String ITERABLE_PARAM_NAME = "multiParam";
private static final String[] ITERABLE_PARAM_EXPECTED = {"value1", "value2"}; private static final String[] ITERABLE_PARAM_EXPECTED = {"value1", "value2"};
private static final Iterable ITERABLE_PARAM_VALUE = Arrays.asList(ITERABLE_PARAM_EXPECTED); private static final Iterable<String> ITERABLE_PARAM_VALUE = Arrays.asList(ITERABLE_PARAM_EXPECTED);
private static final String INT_ARR_PARAM_NAME = "intArrayParam"; private static final String INT_ARR_PARAM_NAME = "intArrayParam";
private static final String[] INT_ARR_PARAM_EXPECTED = {"-42", "4711"}; private static final String[] INT_ARR_PARAM_EXPECTED = {"-42", "4711"};
...@@ -73,10 +75,12 @@ public class SolrQueryExecutorTest ...@@ -73,10 +75,12 @@ public class SolrQueryExecutorTest
private static final Object SINGLE_PARAM_VALUE = new Object(); private static final Object SINGLE_PARAM_VALUE = new Object();
private static final Object SINGLE_PARAM_EXPECTED = SINGLE_PARAM_VALUE.toString(); private static final Object SINGLE_PARAM_EXPECTED = SINGLE_PARAM_VALUE.toString();
@Rule
public final MockitoComponentMockingRule<QueryExecutor> componentManager = public final MockitoComponentMockingRule<QueryExecutor> componentManager =
new MockitoComponentMockingRule<QueryExecutor>(SolrQueryExecutor.class); new MockitoComponentMockingRule<QueryExecutor>(SolrQueryExecutor.class);
@Rule
public final MockitoOldcoreRule oldCore = new MockitoOldcoreRule(this.componentManager);
@Test @Test
public void testExecutorRegistration() throws Exception public void testExecutorRegistration() throws Exception
{ {
...@@ -99,6 +103,9 @@ public Object answer(InvocationOnMock invocation) throws Throwable { ...@@ -99,6 +103,9 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
Assert.assertArrayEquals(STR_ARR_PARAM_EXPECTED, solrQuery.getParams(STR_ARR_PARAM_NAME)); Assert.assertArrayEquals(STR_ARR_PARAM_EXPECTED, solrQuery.getParams(STR_ARR_PARAM_NAME));
Assert.assertEquals(SINGLE_PARAM_EXPECTED, solrQuery.get(SINGLE_PARAM_NAME)); Assert.assertEquals(SINGLE_PARAM_EXPECTED, solrQuery.get(SINGLE_PARAM_NAME));
// Check that the default list of supported locales is taken from the wiki configuration.
Assert.assertEquals("en,fr,de", solrQuery.get("xwiki.supportedLocales"));
QueryResponse r = mock(QueryResponse.class); QueryResponse r = mock(QueryResponse.class);
when(r.getResults()).thenReturn(new SolrDocumentList()); when(r.getResults()).thenReturn(new SolrDocumentList());
return r; return r;
...@@ -115,6 +122,11 @@ public Object answer(InvocationOnMock invocation) throws Throwable { ...@@ -115,6 +122,11 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
query.bindValue(STR_ARR_PARAM_NAME, STR_ARR_PARAM_VALUE); query.bindValue(STR_ARR_PARAM_NAME, STR_ARR_PARAM_VALUE);
query.bindValue(SINGLE_PARAM_NAME, SINGLE_PARAM_VALUE); query.bindValue(SINGLE_PARAM_NAME, SINGLE_PARAM_VALUE);
// The default list of supported locales should be taken from the wiki configuration.
XWikiContext xcontext = this.oldCore.getXWikiContext();
when(this.oldCore.getMockXWiki().getAvailableLocales(xcontext)).thenReturn(
Arrays.asList(Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN));
componentManager.getComponentUnderTest().execute(query); componentManager.getComponentUnderTest().execute(query);
} }
} }
...@@ -37,11 +37,6 @@ ...@@ -37,11 +37,6 @@
<xwiki.jacoco.instructionRatio>0.0</xwiki.jacoco.instructionRatio> <xwiki.jacoco.instructionRatio>0.0</xwiki.jacoco.instructionRatio>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-oldcore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.xwiki.platform</groupId> <groupId>org.xwiki.platform</groupId>
<artifactId>xwiki-platform-rest-server</artifactId> <artifactId>xwiki-platform-rest-server</artifactId>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
...@@ -48,7 +47,6 @@ ...@@ -48,7 +47,6 @@
import org.xwiki.rest.resources.pages.PageResource; import org.xwiki.rest.resources.pages.PageResource;
import org.xwiki.rest.resources.pages.PageTranslationResource; import org.xwiki.rest.resources.pages.PageTranslationResource;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.XWikiException;
/** /**
...@@ -60,9 +58,6 @@ ...@@ -60,9 +58,6 @@
@Singleton @Singleton
public class SOLRSearchSource extends AbstractSearchSource public class SOLRSearchSource extends AbstractSearchSource
{ {
@Inject
protected Provider<XWikiContext> xcontextProvider;
@Inject @Inject
protected QueryManager queryManager; protected QueryManager queryManager;
...@@ -117,11 +112,6 @@ public List<SearchResult> search(String queryString, String defaultWikiName, Str ...@@ -117,11 +112,6 @@ public List<SearchResult> search(String queryString, String defaultWikiName, Str
} }
} }
// Supported locales
XWikiContext xcontext = this.xcontextProvider.get();
query.bindValue("xwiki.supportedLocales",
StringUtils.join(xcontext.getWiki().getAvailableLocales(xcontext), ','));
// TODO: current locale filtering ? // TODO: current locale filtering ?
query.bindValue("fq", fq); query.bindValue("fq", fq);
......
...@@ -578,7 +578,6 @@ ...@@ -578,7 +578,6 @@
#set ($discard = $query.setLimit($rows)) #set ($discard = $query.setLimit($rows))
#set ($discard = $query.setOffset($start)) #set ($discard = $query.setOffset($start))
#set ($discard = $query.bindValue('sort', "${sort} ${sortOrder}")) #set ($discard = $query.bindValue('sort', "${sort} ${sortOrder}"))
#setSupportedLocales($query)
#setQueryFields($query) #setQueryFields($query)
#setFacetFields($query) #setFacetFields($query)
#setFilterQuery($query) #setFilterQuery($query)
...@@ -590,27 +589,6 @@ ...@@ -590,27 +589,6 @@
#set ($searchResponse = $query.execute()[0]) #set ($searchResponse = $query.execute()[0])
#end #end
#**
* We have to set the list of supported locales so the names of the fields that are indexed in multiple languages are
* expanded in the search query. For instance, the query "title:text" will be expanded to "title__:text OR
* title_en:text OR title_fr:text" if the list of supported locales is [en, fr].
*#
#macro (setSupportedLocales $query)
#set ($supportedLanguagesRaw = $xwiki.getXWikiPreference('languages').split('[, |]'))
#set ($supportedLanguages = [])
#foreach ($supportedLanguage in $supportedLanguagesRaw)
#if ($supportedLanguage.trim() != '')
#set ($discard = $supportedLanguages.add($supportedLanguage))
#end
#end
## Make sure the default language is included.
#set ($defaultLanguage = $xwiki.getXWikiPreference('default_language', 'en'))
#if (!$supportedLanguages.contains($defaultLanguage))
#set ($discard = $supportedLanguages.add($defaultLanguage))
#end
#set ($discard = $query.bindValue('xwiki.supportedLocales', $stringtool.join($supportedLanguages, ',')))
#end
#macro (setQueryFields $query) #macro (setQueryFields $query)
## Specify which index fields are matched when a free text search is performed. ## Specify which index fields are matched when a free text search is performed.
#if ($boost == '') #if ($boost == '')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment