Pārlūkot izejas kodu

fix #2829 Enable specifying RankFusionSearcher via system properties configuration.

Shinsuke Sugaya 11 mēneši atpakaļ
vecāks
revīzija
9e78a39cc1

+ 2 - 0
src/main/java/org/codelibs/fess/helper/SystemHelper.java

@@ -517,6 +517,8 @@ public class SystemHelper {
             ComponentUtil.getJobManager().reboot();
             ComponentUtil.getJobManager().reboot();
         }
         }
         updateSystemProperties();
         updateSystemProperties();
+
+        ComponentUtil.getRankFusionProcessor().update();
     }
     }
 
 
     public void updateSystemProperties() {
     public void updateSystemProperties() {

+ 53 - 12
src/main/java/org/codelibs/fess/rank/fusion/RankFusionProcessor.java

@@ -17,6 +17,7 @@ package org.codelibs.fess.rank.fusion;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.List;
@@ -28,11 +29,15 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.Logger;
 import org.apache.lucene.search.TotalHits.Relation;
 import org.apache.lucene.search.TotalHits.Relation;
 import org.codelibs.core.collection.ArrayUtil;
 import org.codelibs.core.collection.ArrayUtil;
+import org.codelibs.core.concurrent.CommonPoolUtil;
+import org.codelibs.core.lang.StringUtil;
+import org.codelibs.core.stream.StreamUtil;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.entity.FacetInfo;
 import org.codelibs.fess.entity.FacetInfo;
 import org.codelibs.fess.entity.GeoInfo;
 import org.codelibs.fess.entity.GeoInfo;
@@ -65,6 +70,8 @@ public class RankFusionProcessor implements AutoCloseable {
 
 
     protected int windowSize;
     protected int windowSize;
 
 
+    protected Set<String> availableSearcherNameSet;
+
     @PostConstruct
     @PostConstruct
     public void init() {
     public void init() {
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
         final FessConfig fessConfig = ComponentUtil.getFessConfig();
@@ -77,6 +84,24 @@ public class RankFusionProcessor implements AutoCloseable {
         } else {
         } else {
             this.windowSize = windowSize;
             this.windowSize = windowSize;
         }
         }
+        load();
+    }
+
+    public void update() {
+        CommonPoolUtil.execute(this::load);
+    }
+
+    protected void load() {
+        final String value = System.getProperty("rank.fusion.searchers");
+        if (StringUtil.isBlank(value)) {
+            availableSearcherNameSet = Collections.emptySet();
+        } else {
+            availableSearcherNameSet = StreamUtil.split(value, ",")
+                    .get(stream -> stream.map(String::trim).filter(StringUtil::isNotBlank).collect(Collectors.toUnmodifiableSet()));
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("availableSearcherNameSet={}", availableSearcherNameSet);
+        }
     }
     }
 
 
     @Override
     @Override
@@ -98,14 +123,30 @@ public class RankFusionProcessor implements AutoCloseable {
 
 
     public List<Map<String, Object>> search(final String query, final SearchRequestParams params,
     public List<Map<String, Object>> search(final String query, final SearchRequestParams params,
             final OptionalThing<FessUserBean> userBean) {
             final OptionalThing<FessUserBean> userBean) {
-        if (searchers.length == 1) {
-            return searchWithMainSearcher(query, params, userBean);
+        final RankFusionSearcher[] availableSearchers = getAvailableSearchers();
+        if (availableSearchers.length == 1) {
+            return searchWithMainSearcher(availableSearchers[0], query, params, userBean);
         }
         }
-        return searchWithMultipleSearchers(query, params, userBean);
+        return searchWithMultipleSearchers(availableSearchers, query, params, userBean);
     }
     }
 
 
-    protected List<Map<String, Object>> searchWithMultipleSearchers(final String query, final SearchRequestParams params,
-            final OptionalThing<FessUserBean> userBean) {
+    protected RankFusionSearcher[] getAvailableSearchers() {
+        if (availableSearcherNameSet.isEmpty()) {
+            return searchers;
+        }
+        final RankFusionSearcher[] availableSearchers = Arrays.stream(searchers)
+                .filter(searcher -> availableSearcherNameSet.contains(searcher.getName())).toArray(n -> new RankFusionSearcher[n]);
+        if (availableSearchers.length == 0) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("No available searchers from {}", availableSearcherNameSet);
+            }
+            return new RankFusionSearcher[] { searchers[0] };
+        }
+        return availableSearchers;
+    }
+
+    protected List<Map<String, Object>> searchWithMultipleSearchers(final RankFusionSearcher[] searchers, final String query,
+            final SearchRequestParams params, final OptionalThing<FessUserBean> userBean) {
         if (logger.isDebugEnabled()) {
         if (logger.isDebugEnabled()) {
             logger.debug("Send {} to the searchers.", query);
             logger.debug("Send {} to the searchers.", query);
         }
         }
@@ -192,13 +233,13 @@ public class RankFusionProcessor implements AutoCloseable {
                         final Map<String, Object> baseDoc = scoreDocMap.get(id);
                         final Map<String, Object> baseDoc = scoreDocMap.get(id);
                         final float oldScore = toFloat(baseDoc.get(scoreField));
                         final float oldScore = toFloat(baseDoc.get(scoreField));
                         baseDoc.put(scoreField, oldScore + score);
                         baseDoc.put(scoreField, oldScore + score);
-                        final String[] searchers = DocumentUtil.getValue(doc, Constants.SEARCHER, String[].class);
-                        if (searchers != null) {
+                        final String[] searcherNames = DocumentUtil.getValue(doc, Constants.SEARCHER, String[].class);
+                        if (searcherNames != null) {
                             final String[] baseSearchers = DocumentUtil.getValue(baseDoc, Constants.SEARCHER, String[].class);
                             final String[] baseSearchers = DocumentUtil.getValue(baseDoc, Constants.SEARCHER, String[].class);
                             if (baseSearchers != null) {
                             if (baseSearchers != null) {
-                                baseDoc.put(Constants.SEARCHER, ArrayUtil.addAll(baseSearchers, searchers));
+                                baseDoc.put(Constants.SEARCHER, ArrayUtil.addAll(baseSearchers, searcherNames));
                             } else {
                             } else {
-                                baseDoc.put(Constants.SEARCHER, searchers);
+                                baseDoc.put(Constants.SEARCHER, searcherNames);
                             }
                             }
                         }
                         }
                     } else {
                     } else {
@@ -248,13 +289,13 @@ public class RankFusionProcessor implements AutoCloseable {
         return docs.subList(fromIndex, toIndex);
         return docs.subList(fromIndex, toIndex);
     }
     }
 
 
-    protected List<Map<String, Object>> searchWithMainSearcher(final String query, final SearchRequestParams params,
-            final OptionalThing<FessUserBean> userBean) {
+    protected List<Map<String, Object>> searchWithMainSearcher(final RankFusionSearcher searcher, final String query,
+            final SearchRequestParams params, final OptionalThing<FessUserBean> userBean) {
         if (logger.isDebugEnabled()) {
         if (logger.isDebugEnabled()) {
             logger.debug("Send {} to the main searcher.", query);
             logger.debug("Send {} to the main searcher.", query);
         }
         }
         final int pageSize = params.getPageSize();
         final int pageSize = params.getPageSize();
-        final SearchResult searchResult = searchers[0].search(query, params, userBean);
+        final SearchResult searchResult = searcher.search(query, params, userBean);
         return createResponseList(searchResult.getDocumentList(), searchResult.getAllRecordCount(),
         return createResponseList(searchResult.getDocumentList(), searchResult.getAllRecordCount(),
                 searchResult.getAllRecordCountRelation(), searchResult.getQueryTime(), searchResult.isPartialResults(),
                 searchResult.getAllRecordCountRelation(), searchResult.getQueryTime(), searchResult.isPartialResults(),
                 searchResult.getFacetResponse(), params.getStartPosition(), pageSize, 0);
                 searchResult.getFacetResponse(), params.getStartPosition(), pageSize, 0);