View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.score;
17  
18  import java.util.Arrays;
19  import java.util.Map;
20  import java.util.function.Function;
21  
22  import org.apache.logging.log4j.LogManager;
23  import org.apache.logging.log4j.Logger;
24  import org.codelibs.core.lang.StringUtil;
25  import org.codelibs.fesen.action.bulk.BulkRequestBuilder;
26  import org.codelibs.fesen.action.bulk.BulkResponse;
27  import org.codelibs.fesen.action.search.SearchResponse;
28  import org.codelibs.fesen.action.update.UpdateRequestBuilder;
29  import org.codelibs.fesen.index.query.QueryBuilders;
30  import org.codelibs.fesen.script.Script;
31  import org.codelibs.fesen.script.ScriptType;
32  import org.codelibs.fesen.search.SearchHit;
33  import org.codelibs.fess.es.client.SearchEngineClient;
34  import org.codelibs.fess.mylasta.direction.FessConfig;
35  import org.codelibs.fess.util.ComponentUtil;
36  
37  public abstract class ScoreBooster {
38      private static final Logger logger = LogManager.getLogger(ScoreBooster.class);
39  
40      protected BulkRequestBuilder bulkRequestBuilder = null;
41  
42      protected int priority = 1;
43  
44      protected String requestTimeout = "1m";
45  
46      protected int requestCacheSize = 1000;
47  
48      protected String scriptLang = "painless";
49  
50      protected String scriptCode = null;
51  
52      protected Function<Map<String, Object>, String[]> idFinder = params -> {
53          final FessConfig fessConfig = ComponentUtil.getFessConfig();
54          final SearchEngineClient client = ComponentUtil.getSearchEngineClient();
55          final String index = fessConfig.getIndexDocumentUpdateIndex();
56          final Object url = params.get("url");
57          if (url == null) {
58              return StringUtil.EMPTY_STRINGS;
59          }
60          final SearchResponse response = client.prepareSearch(index).setQuery(QueryBuilders.termQuery(fessConfig.getIndexFieldUrl(), url))
61                  .setFetchSource(false).setSize(fessConfig.getPageScoreBoosterMaxFetchSizeAsInteger()).execute().actionGet(requestTimeout);
62          return Arrays.stream(response.getHits().getHits()).map(SearchHit::getId).toArray(n -> new String[n]);
63      };
64  
65      protected Function<Map<String, Object>, Long> requestHandler = params -> {
66          final FessConfig fessConfig = ComponentUtil.getFessConfig();
67          final String[] ids = idFinder.apply(params);
68          if (ids.length == 0) {
69              return 0L;
70          }
71          final SearchEngineClient client = ComponentUtil.getSearchEngineClient();
72          if (bulkRequestBuilder == null) {
73              bulkRequestBuilder = client.prepareBulk();
74          }
75          final String index = fessConfig.getIndexDocumentUpdateIndex();
76          for (final String id : ids) {
77              bulkRequestBuilder.add(client.prepareUpdate().setIndex(index).setId(id)
78                      .setScript(new Script(ScriptType.INLINE, scriptLang, scriptCode, params)));
79          }
80          if (bulkRequestBuilder.numberOfActions() > requestCacheSize) {
81              flush();
82          }
83          return (long) ids.length;
84      };
85  
86      public abstract long process();
87  
88      protected void enable() {
89          final ScoreUpdater scoreUpdater = ComponentUtil.getComponent("scoreUpdater");
90          scoreUpdater.addScoreBooster(this);
91      }
92  
93      protected long updateScore(final Map<String, Object> params) {
94          return requestHandler.apply(params);
95      }
96  
97      protected UpdateRequestBuilder createUpdateRequestBuilder() {
98          final FessConfig fessConfig = ComponentUtil.getFessConfig();
99          return ComponentUtil.getSearchEngineClient().prepareUpdate().setIndex(fessConfig.getIndexDocumentSearchIndex());
100     }
101 
102     protected void flush() {
103         if (bulkRequestBuilder != null) {
104             final BulkResponse response = bulkRequestBuilder.execute().actionGet(requestTimeout);
105             if (response.hasFailures()) {
106                 logger.warn("Failed to update scores: {}", response.buildFailureMessage());
107             }
108             bulkRequestBuilder = null;
109         }
110     }
111 
112     public int getPriority() {
113         return this.priority;
114     }
115 
116     public void setPriority(final int priority) {
117         this.priority = priority;
118     }
119 
120     public void setRequestTimeout(final String bulkRequestTimeout) {
121         this.requestTimeout = bulkRequestTimeout;
122     }
123 
124     public void setRequestCacheSize(final int requestCacheSize) {
125         this.requestCacheSize = requestCacheSize;
126     }
127 
128     public void setScriptLang(final String scriptLang) {
129         this.scriptLang = scriptLang;
130     }
131 
132     public void setScriptCode(final String scriptCode) {
133         this.scriptCode = scriptCode;
134     }
135 }