diff --git a/src/main/java/org/olat/search/service/SearchServiceImpl.java b/src/main/java/org/olat/search/service/SearchServiceImpl.java index f366ae6bcafe0937ea0e225f4d064998b9f12b0b..a6e3e07392eebe98a940c2ad1d079247b35ed31f 100644 --- a/src/main/java/org/olat/search/service/SearchServiceImpl.java +++ b/src/main/java/org/olat/search/service/SearchServiceImpl.java @@ -82,6 +82,7 @@ import org.olat.search.service.indexer.Index; import org.olat.search.service.indexer.IndexerEvent; import org.olat.search.service.indexer.LifeFullIndexer; import org.olat.search.service.indexer.MainIndexer; +import org.olat.search.service.searcher.ConditionalQueryAnalyzer; import org.olat.search.service.searcher.JmsSearchProvider; import org.olat.search.service.spell.SearchSpellChecker; import org.quartz.JobDetail; @@ -104,7 +105,8 @@ public class SearchServiceImpl implements SearchService, GenericEventListener { private Scheduler scheduler; private CoordinatorManager coordinatorManager; - private Analyzer analyzer; + private final Analyzer analyzer; + private final ConditionalQueryAnalyzer conditionalQueryAnalyzer; private LifeFullIndexer lifeIndexer; private SearchSpellChecker searchSpellChecker; @@ -148,6 +150,7 @@ public class SearchServiceImpl implements SearchService, GenericEventListener { this.mainIndexer = mainIndexer; this.coordinatorManager = coordinatorManager; analyzer = new StandardAnalyzer(); + conditionalQueryAnalyzer = new ConditionalQueryAnalyzer(); searchProvider.setSearchService(this); coordinatorManager.getCoordinator().getEventBus().registerFor(this, null, IndexerEvent.INDEX_ORES); } @@ -405,7 +408,7 @@ public class SearchServiceImpl implements SearchService, GenericEventListener { if(condQueries != null && !condQueries.isEmpty()) { for(String condQueryString:condQueries) { - QueryParser condQueryParser = new QueryParser(condQueryString, analyzer); + QueryParser condQueryParser = new QueryParser(condQueryString, conditionalQueryAnalyzer); condQueryParser.setLocale(locale); Query condQuery = condQueryParser.parse(condQueryString); query.add(condQuery, Occur.MUST); diff --git a/src/main/java/org/olat/search/service/searcher/ConditionalQueryAnalyzer.java b/src/main/java/org/olat/search/service/searcher/ConditionalQueryAnalyzer.java new file mode 100644 index 0000000000000000000000000000000000000000..d0192a0d91e9719c2cad6a6c5541867552887a68 --- /dev/null +++ b/src/main/java/org/olat/search/service/searcher/ConditionalQueryAnalyzer.java @@ -0,0 +1,76 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.search.service.searcher; + +import java.io.Reader; + +import org.apache.lucene.analysis.LowerCaseFilter; +import org.apache.lucene.analysis.StopFilter; +import org.apache.lucene.analysis.StopwordAnalyzerBase; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.en.EnglishAnalyzer; +import org.apache.lucene.analysis.standard.StandardTokenizer; +import org.olat.search.model.AbstractOlatDocument; + +/** + * This analyzer is based on the StandardAnalyzer with the english + * stop words, but it doesn't normalize the fields resourceurl and + * resourceurlmd5 to lower case. This is essential because the business + * path is case sensitive and the standard analyzers of Lucene lower + * case the search queries. + * + * + * Initial date: 17 janv. 2019<br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ConditionalQueryAnalyzer extends StopwordAnalyzerBase { + + private static final int maxTokenLength = 255; + public ConditionalQueryAnalyzer() { + super(EnglishAnalyzer.ENGLISH_STOP_WORDS_SET); + } + + @Override + protected TokenStreamComponents createComponents(final String fieldName) { + final StandardTokenizer src = new StandardTokenizer(); + src.setMaxTokenLength(maxTokenLength); + TokenStream tok = new LowerCaseFilter(src); + tok = new StopFilter(tok, stopwords); + return new TokenStreamComponents(src, tok) { + @Override + protected void setReader(final Reader reader) { + // So that if maxTokenLength was changed, the change takes + // effect next time tokenStream is called: + src.setMaxTokenLength(maxTokenLength); + super.setReader(reader); + } + }; + } + + @Override + protected TokenStream normalize(String fieldName, TokenStream in) { + if(AbstractOlatDocument.RESOURCEURL_FIELD_NAME.equals(fieldName) || AbstractOlatDocument.RESOURCEURL_MD5_FIELD_NAME.equals(fieldName)) { + return in; + } + return new LowerCaseFilter(in); + } +}