1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.helper;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.codelibs.fesen.action.search.SearchResponse;
25 import org.codelibs.fesen.index.query.QueryBuilder;
26 import org.codelibs.fesen.index.query.QueryBuilders;
27 import org.codelibs.fess.es.client.SearchEngineClient;
28 import org.codelibs.fess.mylasta.direction.FessConfig;
29 import org.codelibs.fess.thumbnail.ThumbnailManager;
30 import org.codelibs.fess.util.ComponentUtil;
31 import org.codelibs.fess.util.DocList;
32 import org.codelibs.fess.util.MemoryUtil;
33
34 public class IndexingHelper {
35 private static final Logger logger = LogManager.getLogger(IndexingHelper.class);
36
37 protected int maxRetryCount = 5;
38
39 protected int defaultRowSize = 100;
40
41 protected long requestInterval = 500;
42
43 public void sendDocuments(final SearchEngineClient searchEngineClient, final DocList docList) {
44 if (docList.isEmpty()) {
45 return;
46 }
47 final FessConfig fessConfig = ComponentUtil.getFessConfig();
48 final long execTime = System.currentTimeMillis();
49 if (logger.isDebugEnabled()) {
50 logger.debug("Sending {} documents to a server.", docList.size());
51 }
52 try {
53 if (fessConfig.isThumbnailCrawlerEnabled()) {
54 final ThumbnailManager thumbnailManager = ComponentUtil.getThumbnailManager();
55 docList.stream().forEach(doc -> {
56 if (!thumbnailManager.offer(doc)) {
57 if (logger.isDebugEnabled()) {
58 logger.debug("Removing {} from {}", doc.get(fessConfig.getIndexFieldThumbnail()),
59 doc.get(fessConfig.getIndexFieldUrl()));
60 }
61 doc.remove(fessConfig.getIndexFieldThumbnail());
62 }
63 });
64 }
65 final CrawlingConfigHelper crawlingConfigHelper = ComponentUtil.getCrawlingConfigHelper();
66 synchronized (searchEngineClient) {
67 deleteOldDocuments(searchEngineClient, docList);
68 searchEngineClient.addAll(fessConfig.getIndexDocumentUpdateIndex(), docList, (doc, builder) -> {
69 final String configId = (String) doc.get(fessConfig.getIndexFieldConfigId());
70 crawlingConfigHelper.getPipeline(configId).ifPresent(s -> builder.setPipeline(s));
71 });
72 }
73 if (logger.isInfoEnabled()) {
74 if (docList.getContentSize() > 0) {
75 logger.info("Sent {} docs (Doc:{process {}ms, send {}ms, size {}}, {})", docList.size(), docList.getProcessingTime(),
76 (System.currentTimeMillis() - execTime), MemoryUtil.byteCountToDisplaySize(docList.getContentSize()),
77 MemoryUtil.getMemoryUsageLog());
78 } else {
79 logger.info("Sent {} docs (Doc:{send {}ms}, {})", docList.size(), (System.currentTimeMillis() - execTime),
80 MemoryUtil.getMemoryUsageLog());
81 }
82 }
83 } finally {
84 docList.clear();
85 }
86 }
87
88 private void deleteOldDocuments(final SearchEngineClient searchEngineClient, final DocList docList) {
89 final FessConfig fessConfig = ComponentUtil.getFessConfig();
90
91 final List<String> docIdList = new ArrayList<>();
92 for (final Map<String, Object> inputDoc : docList) {
93 final Object idValue = inputDoc.get(fessConfig.getIndexFieldId());
94 if (idValue == null) {
95 continue;
96 }
97
98 final Object configIdValue = inputDoc.get(fessConfig.getIndexFieldConfigId());
99 if (configIdValue == null) {
100 continue;
101 }
102
103 final QueryBuilder queryBuilder = QueryBuilders.boolQuery()
104 .must(QueryBuilders.termQuery(fessConfig.getIndexFieldUrl(), inputDoc.get(fessConfig.getIndexFieldUrl())))
105 .filter(QueryBuilders.termQuery(fessConfig.getIndexFieldConfigId(), configIdValue));
106
107 final List<Map<String, Object>> docs = getDocumentListByQuery(searchEngineClient, queryBuilder,
108 new String[] { fessConfig.getIndexFieldId(), fessConfig.getIndexFieldDocId() });
109 for (final Map<String, Object> doc : docs) {
110 final Object oldIdValue = doc.get(fessConfig.getIndexFieldId());
111 if (!idValue.equals(oldIdValue) && oldIdValue != null) {
112 final Object oldDocIdValue = doc.get(fessConfig.getIndexFieldDocId());
113 if (oldDocIdValue != null) {
114 docIdList.add(oldDocIdValue.toString());
115 }
116 }
117 }
118 if (logger.isDebugEnabled()) {
119 logger.debug("{} => {}", queryBuilder, docs);
120 }
121 }
122 if (!docIdList.isEmpty()) {
123 searchEngineClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(),
124 QueryBuilders.idsQuery().addIds(docIdList.stream().toArray(n -> new String[n])));
125
126 }
127 }
128
129 public boolean updateDocument(final SearchEngineClient searchEngineClient, final String id, final String field, final Object value) {
130 final FessConfig fessConfig = ComponentUtil.getFessConfig();
131 return searchEngineClient.update(fessConfig.getIndexDocumentUpdateIndex(), id, field, value);
132 }
133
134 public boolean deleteDocument(final SearchEngineClient searchEngineClient, final String id) {
135 final FessConfig fessConfig = ComponentUtil.getFessConfig();
136 return searchEngineClient.delete(fessConfig.getIndexDocumentUpdateIndex(), id);
137 }
138
139 public long deleteDocumentByUrl(final SearchEngineClient searchEngineClient, final String url) {
140 final FessConfig fessConfig = ComponentUtil.getFessConfig();
141 return searchEngineClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(),
142 QueryBuilders.termQuery(fessConfig.getIndexFieldUrl(), url));
143 }
144
145 public long deleteDocumentsByDocId(final SearchEngineClient searchEngineClient, final List<String> docIdList) {
146 final FessConfig fessConfig = ComponentUtil.getFessConfig();
147 return searchEngineClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(),
148 QueryBuilders.idsQuery().addIds(docIdList.stream().toArray(n -> new String[n])));
149 }
150
151 public long deleteDocumentByQuery(final SearchEngineClient searchEngineClient, final QueryBuilder queryBuilder) {
152 final FessConfig fessConfig = ComponentUtil.getFessConfig();
153 return searchEngineClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(), queryBuilder);
154 }
155
156 public Map<String, Object> getDocument(final SearchEngineClient searchEngineClient, final String id, final String[] fields) {
157 final FessConfig fessConfig = ComponentUtil.getFessConfig();
158 return searchEngineClient.getDocument(fessConfig.getIndexDocumentUpdateIndex(), builder -> {
159 builder.setQuery(QueryBuilders.idsQuery().addIds(id));
160 builder.setFetchSource(fields, null);
161 return true;
162 }).orElse(null);
163 }
164
165 public List<Map<String, Object>> getDocumentListByPrefixId(final SearchEngineClient searchEngineClient, final String id,
166 final String[] fields) {
167 final FessConfig fessConfig = ComponentUtil.getFessConfig();
168 final QueryBuilder queryBuilder = QueryBuilders.prefixQuery(fessConfig.getIndexFieldId(), id);
169 return getDocumentListByQuery(searchEngineClient, queryBuilder, fields);
170 }
171
172 public void deleteChildDocument(final SearchEngineClient searchEngineClient, final String id) {
173 final FessConfig fessConfig = ComponentUtil.getFessConfig();
174 searchEngineClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(),
175 QueryBuilders.termQuery(fessConfig.getIndexFieldParentId(), id));
176 }
177
178 public List<Map<String, Object>> getChildDocumentList(final SearchEngineClient searchEngineClient, final String id,
179 final String[] fields) {
180 final FessConfig fessConfig = ComponentUtil.getFessConfig();
181 final QueryBuilder queryBuilder = QueryBuilders.termQuery(fessConfig.getIndexFieldParentId(), id);
182 return getDocumentListByQuery(searchEngineClient, queryBuilder, fields);
183 }
184
185 protected List<Map<String, Object>> getDocumentListByQuery(final SearchEngineClient searchEngineClient, final QueryBuilder queryBuilder,
186 final String[] fields) {
187 final FessConfig fessConfig = ComponentUtil.getFessConfig();
188
189 final SearchResponse countResponse = searchEngineClient.prepareSearch(fessConfig.getIndexDocumentUpdateIndex())
190 .setQuery(queryBuilder).setSize(0).execute().actionGet(fessConfig.getIndexSearchTimeout());
191 final long numFound = countResponse.getHits().getTotalHits().value;
192
193
194 return searchEngineClient.getDocumentList(fessConfig.getIndexDocumentUpdateIndex(), requestBuilder -> {
195 requestBuilder.setQuery(queryBuilder).setSize((int) numFound);
196 if (fields != null) {
197 requestBuilder.setFetchSource(fields, null);
198 }
199 return true;
200 });
201
202 }
203
204 public long deleteBySessionId(final String sessionId) {
205 final FessConfig fessConfig = ComponentUtil.getFessConfig();
206 final String index = fessConfig.getIndexDocumentUpdateIndex();
207 final QueryBuilder queryBuilder = QueryBuilders.termQuery(fessConfig.getIndexFieldSegment(), sessionId);
208 return deleteByQueryBuilder(index, queryBuilder);
209 }
210
211 public long deleteByConfigId(final String configId) {
212 final FessConfig fessConfig = ComponentUtil.getFessConfig();
213 final String index = fessConfig.getIndexDocumentUpdateIndex();
214 final QueryBuilder queryBuilder = QueryBuilders.termQuery(fessConfig.getIndexFieldConfigId(), configId);
215 return deleteByQueryBuilder(index, queryBuilder);
216 }
217
218 public long deleteByVirtualHost(final String virtualHost) {
219 final FessConfig fessConfig = ComponentUtil.getFessConfig();
220 final String index = fessConfig.getIndexDocumentUpdateIndex();
221 final QueryBuilder queryBuilder = QueryBuilders.termQuery(fessConfig.getIndexFieldVirtualHost(), virtualHost);
222 return deleteByQueryBuilder(index, queryBuilder);
223 }
224
225 protected long deleteByQueryBuilder(final String index, final QueryBuilder queryBuilder) {
226 final SearchEngineClient searchEngineClient = ComponentUtil.getSearchEngineClient();
227 searchEngineClient.admin().indices().prepareRefresh(index).execute().actionGet();
228 final long numOfDeleted = searchEngineClient.deleteByQuery(index, queryBuilder);
229 logger.info("Deleted {} old docs.", numOfDeleted);
230 return numOfDeleted;
231 }
232
233 public long calculateDocumentSize(final Map<String, Object> dataMap) {
234 return MemoryUtil.sizeOf(dataMap);
235 }
236
237 public void setMaxRetryCount(final int maxRetryCount) {
238 this.maxRetryCount = maxRetryCount;
239 }
240
241 public void setDefaultRowSize(final int defaultRowSize) {
242 this.defaultRowSize = defaultRowSize;
243 }
244
245 public void setRequestInterval(final long requestInterval) {
246 this.requestInterval = requestInterval;
247 }
248
249 }