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.codelibs.fess.es.client.FessEsClient;
23 import org.codelibs.fess.mylasta.direction.FessConfig;
24 import org.codelibs.fess.thumbnail.ThumbnailManager;
25 import org.codelibs.fess.util.ComponentUtil;
26 import org.codelibs.fess.util.DocList;
27 import org.codelibs.fess.util.MemoryUtil;
28 import org.elasticsearch.action.search.SearchResponse;
29 import org.elasticsearch.index.query.QueryBuilder;
30 import org.elasticsearch.index.query.QueryBuilders;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public class IndexingHelper {
35 private static final Logger logger = LoggerFactory.getLogger(IndexingHelper.class);
36
37 public int maxRetryCount = 5;
38
39 public int defaultRowSize = 100;
40
41 public long requestInterval = 500;
42
43 public void sendDocuments(final FessEsClient fessEsClient, final DocList docList) {
44 if (docList.isEmpty()) {
45 return;
46 }
47 final FessConfig fessConfig = ComponentUtil.getFessConfig();
48 if (fessConfig.isResultCollapsed()) {
49 docList.forEach(doc -> {
50 doc.put("content_minhash", doc.get(fessConfig.getIndexFieldContent()));
51 });
52 }
53 final long execTime = System.currentTimeMillis();
54 if (logger.isDebugEnabled()) {
55 logger.debug("Sending " + docList.size() + " documents to a server.");
56 }
57 try {
58 if (fessConfig.isThumbnailCrawlerEnabled()) {
59 final ThumbnailManager thumbnailManager = ComponentUtil.getThumbnailManager();
60 docList.stream().forEach(
61 doc -> {
62 if (!thumbnailManager.offer(doc)) {
63 if (logger.isDebugEnabled()) {
64 logger.debug("Removing " + doc.get(fessConfig.getIndexFieldThumbnail()) + " from "
65 + doc.get(fessConfig.getIndexFieldUrl()));
66 }
67 doc.remove(fessConfig.getIndexFieldThumbnail());
68 }
69 });
70 }
71 synchronized (fessEsClient) {
72 deleteOldDocuments(fessEsClient, docList);
73 fessEsClient.addAll(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), docList);
74 }
75 if (logger.isInfoEnabled()) {
76 if (docList.getContentSize() > 0) {
77 logger.info("Sent " + docList.size() + " docs (Doc:{process " + docList.getProcessingTime() + "ms, send "
78 + (System.currentTimeMillis() - execTime) + "ms, size "
79 + MemoryUtil.byteCountToDisplaySize(docList.getContentSize()) + "}, " + MemoryUtil.getMemoryUsageLog() + ")");
80 } else {
81 logger.info("Sent " + docList.size() + " docs (Doc:{send " + (System.currentTimeMillis() - execTime) + "ms}, "
82 + MemoryUtil.getMemoryUsageLog() + ")");
83 }
84 }
85 } finally {
86 docList.clear();
87 }
88 }
89
90 private void deleteOldDocuments(final FessEsClient fessEsClient, final DocList docList) {
91 final FessConfig fessConfig = ComponentUtil.getFessConfig();
92
93 final List<String> docIdList = new ArrayList<>();
94 for (final Map<String, Object> inputDoc : docList) {
95 final Object idValue = inputDoc.get(fessConfig.getIndexFieldId());
96 if (idValue == null) {
97 continue;
98 }
99
100 final Object configIdValue = inputDoc.get(fessConfig.getIndexFieldConfigId());
101 if (configIdValue == null) {
102 continue;
103 }
104
105 final QueryBuilder queryBuilder =
106 QueryBuilders.boolQuery()
107 .must(QueryBuilders.termQuery(fessConfig.getIndexFieldUrl(), inputDoc.get(fessConfig.getIndexFieldUrl())))
108 .filter(QueryBuilders.termQuery(fessConfig.getIndexFieldConfigId(), configIdValue));
109
110 final List<Map<String, Object>> docs =
111 getDocumentListByQuery(fessEsClient, queryBuilder,
112 new String[] { fessConfig.getIndexFieldId(), fessConfig.getIndexFieldDocId() });
113 for (final Map<String, Object> doc : docs) {
114 final Object oldIdValue = doc.get(fessConfig.getIndexFieldId());
115 if (!idValue.equals(oldIdValue) && oldIdValue != null) {
116 final Object oldDocIdValue = doc.get(fessConfig.getIndexFieldDocId());
117 if (oldDocIdValue != null) {
118 docIdList.add(oldDocIdValue.toString());
119 }
120 }
121 }
122 if (logger.isDebugEnabled()) {
123 logger.debug(queryBuilder.toString() + " => " + docs);
124 }
125 }
126 if (!docIdList.isEmpty()) {
127 fessEsClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(),
128 QueryBuilders.idsQuery(fessConfig.getIndexDocumentType()).addIds(docIdList.stream().toArray(n -> new String[n])));
129
130 }
131 }
132
133 public boolean updateDocument(final FessEsClient fessEsClient, final String id, final String field, final Object value) {
134 final FessConfig fessConfig = ComponentUtil.getFessConfig();
135 return fessEsClient.update(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), id, field, value);
136 }
137
138 public boolean deleteDocument(final FessEsClient fessEsClient, final String id) {
139 final FessConfig fessConfig = ComponentUtil.getFessConfig();
140 return fessEsClient.delete(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), id, 0);
141 }
142
143 public int deleteDocumentByUrl(final FessEsClient fessEsClient, final String url) {
144 final FessConfig fessConfig = ComponentUtil.getFessConfig();
145 return fessEsClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(),
146 QueryBuilders.termQuery(fessConfig.getIndexFieldUrl(), url));
147 }
148
149 public int deleteDocumentsByDocId(final FessEsClient fessEsClient, final List<String> docIdList) {
150 final FessConfig fessConfig = ComponentUtil.getFessConfig();
151 return fessEsClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), QueryBuilders
152 .idsQuery(fessConfig.getIndexDocumentType()).addIds(docIdList.stream().toArray(n -> new String[n])));
153 }
154
155 public Map<String, Object> getDocument(final FessEsClient fessEsClient, final String id, final String[] fields) {
156 final FessConfig fessConfig = ComponentUtil.getFessConfig();
157 return fessEsClient.getDocument(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(), builder -> {
158 builder.setQuery(QueryBuilders.idsQuery(fessConfig.getIndexDocumentType()).addIds(id));
159 builder.setFetchSource(fields, null);
160 return true;
161 }).orElse(null);
162 }
163
164 public List<Map<String, Object>> getDocumentListByPrefixId(final FessEsClient fessEsClient, final String id, final String[] fields) {
165 final FessConfig fessConfig = ComponentUtil.getFessConfig();
166 final QueryBuilder queryBuilder = QueryBuilders.prefixQuery(fessConfig.getIndexFieldId(), id);
167 return getDocumentListByQuery(fessEsClient, queryBuilder, fields);
168 }
169
170 public void deleteChildDocument(final FessEsClient fessEsClient, final String id) {
171 final FessConfig fessConfig = ComponentUtil.getFessConfig();
172 fessEsClient.deleteByQuery(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(),
173 QueryBuilders.termQuery(fessConfig.getIndexFieldParentId(), id));
174 }
175
176 public List<Map<String, Object>> getChildDocumentList(final FessEsClient fessEsClient, final String id, final String[] fields) {
177 final FessConfig fessConfig = ComponentUtil.getFessConfig();
178 final QueryBuilder queryBuilder = QueryBuilders.termQuery(fessConfig.getIndexFieldParentId(), id);
179 return getDocumentListByQuery(fessEsClient, queryBuilder, fields);
180 }
181
182 protected List<Map<String, Object>> getDocumentListByQuery(final FessEsClient fessEsClient, final QueryBuilder queryBuilder,
183 final String[] fields) {
184 final FessConfig fessConfig = ComponentUtil.getFessConfig();
185
186 final SearchResponse countResponse =
187 fessEsClient.prepareSearch(fessConfig.getIndexDocumentUpdateIndex()).setTypes(fessConfig.getIndexDocumentType())
188 .setQuery(queryBuilder).setSize(0).execute().actionGet(fessConfig.getIndexSearchTimeout());
189 final long numFound = countResponse.getHits().getTotalHits();
190
191
192 return fessEsClient.getDocumentList(fessConfig.getIndexDocumentUpdateIndex(), fessConfig.getIndexDocumentType(),
193 requestBuilder -> {
194 requestBuilder.setQuery(queryBuilder).setSize((int) numFound);
195 if (fields != null) {
196 requestBuilder.setFetchSource(fields, null);
197 }
198 return true;
199 });
200
201 }
202 }