1
14
15 package com.liferay.portal.search.lucene;
16
17 import com.liferay.portal.kernel.dao.orm.QueryUtil;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.search.Document;
21 import com.liferay.portal.kernel.search.DocumentImpl;
22 import com.liferay.portal.kernel.search.Field;
23 import com.liferay.portal.kernel.search.Hits;
24 import com.liferay.portal.kernel.search.HitsImpl;
25 import com.liferay.portal.kernel.search.IndexSearcher;
26 import com.liferay.portal.kernel.search.Query;
27 import com.liferay.portal.kernel.search.SearchException;
28 import com.liferay.portal.kernel.search.Sort;
29 import com.liferay.portal.kernel.util.StringUtil;
30 import com.liferay.portal.kernel.util.Time;
31 import com.liferay.portal.kernel.util.Validator;
32
33 import java.io.IOException;
34
35 import java.util.List;
36
37 import org.apache.lucene.queryParser.ParseException;
38 import org.apache.lucene.search.BooleanQuery;
39 import org.apache.lucene.search.SortField;
40
41
46 public class LuceneIndexSearcherImpl implements IndexSearcher {
47
48 public Hits search(
49 long companyId, Query query, Sort[] sorts, int start, int end)
50 throws SearchException {
51
52 if (_log.isDebugEnabled()) {
53 _log.debug("Query " + query);
54 }
55
56 Hits hits = null;
57
58 org.apache.lucene.search.IndexSearcher searcher = null;
59 org.apache.lucene.search.Sort luceneSort = null;
60
61 try {
62 searcher = LuceneHelperUtil.getSearcher(companyId, true);
63
64 if (sorts != null) {
65 SortField[] sortFields = new SortField[sorts.length];
66
67 for (int i = 0; i < sorts.length; i++) {
68 Sort sort = sorts[i];
69
70 sortFields[i] = new SortField(
71 sort.getFieldName(), sort.getType(), sort.isReverse());
72 }
73
74 luceneSort = new org.apache.lucene.search.Sort(sortFields);
75 }
76
77 long startTime = System.currentTimeMillis();
78
79 org.apache.lucene.search.Hits luceneHits = searcher.search(
80 QueryTranslator.translate(query), luceneSort);
81
82 long endTime = System.currentTimeMillis();
83
84 float searchTime = (float)(endTime - startTime) / Time.SECOND;
85
86 hits = subset(luceneHits, query, startTime, searchTime, start, end);
87 }
88 catch (BooleanQuery.TooManyClauses tmc) {
89 int maxClauseCount = BooleanQuery.getMaxClauseCount();
90
91 BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE);
92
93 try {
94 long startTime = System.currentTimeMillis();
95
96 org.apache.lucene.search.Hits luceneHits = searcher.search(
97 QueryTranslator.translate(query), luceneSort);
98
99 long endTime = System.currentTimeMillis();
100
101 float searchTime = (float)(endTime - startTime) / Time.SECOND;
102
103 hits = subset(
104 luceneHits, query, startTime, searchTime, start, end);
105 }
106 catch (Exception e) {
107 throw new SearchException(e);
108 }
109 finally {
110 BooleanQuery.setMaxClauseCount(maxClauseCount);
111 }
112 }
113 catch (ParseException pe) {
114 _log.error("Query: " + query, pe);
115
116 return new HitsImpl();
117 }
118 catch (Exception e) {
119 throw new SearchException(e);
120 }
121 finally {
122 try {
123 if (searcher != null) {
124 searcher.close();
125 }
126 }
127 catch (IOException ioe) {
128 throw new SearchException(ioe);
129 }
130 }
131
132 if (_log.isDebugEnabled()) {
133 _log.debug(
134 "Search found " + hits.getLength() + " results in " +
135 hits.getSearchTime() + "ms");
136 }
137
138 return hits;
139 }
140
141 protected DocumentImpl getDocument(
142 org.apache.lucene.document.Document oldDoc) {
143
144 DocumentImpl newDoc = new DocumentImpl();
145
146 List<org.apache.lucene.document.Field> oldFields = oldDoc.getFields();
147
148 for (org.apache.lucene.document.Field oldField : oldFields) {
149 String[] values = oldDoc.getValues(oldField.name());
150
151 if ((values != null) && (values.length > 1)) {
152 Field newField = new Field(
153 oldField.name(), values, oldField.isTokenized());
154
155 newDoc.add(newField);
156 }
157 else {
158 Field newField = new Field(
159 oldField.name(), oldField.stringValue(),
160 oldField.isTokenized());
161
162 newDoc.add(newField);
163 }
164 }
165
166 return newDoc;
167 }
168
169 protected String[] getQueryTerms(Query query) {
170 String[] queryTerms = new String[0];
171
172 try {
173 queryTerms = LuceneHelperUtil.getQueryTerms(
174 QueryTranslator.translate(query));
175 }
176 catch (ParseException pe) {
177 _log.error("Query: " + query, pe);
178 }
179
180 return queryTerms;
181 }
182
183 protected String getSnippet(
184 org.apache.lucene.document.Document doc, Query query, String field)
185 throws IOException {
186
187 String[] values = doc.getValues(field);
188
189 String snippet = null;
190
191 if (Validator.isNull(values)) {
192 return snippet;
193 }
194
195 String s = StringUtil.merge(values);
196
197 try {
198 snippet = LuceneHelperUtil.getSnippet(
199 QueryTranslator.translate(query), field, s);
200 }
201 catch (ParseException pe) {
202 _log.error("Query: " + query, pe);
203 }
204
205 return snippet;
206 }
207
208 protected Hits subset(
209 org.apache.lucene.search.Hits luceneHits, Query query,
210 long startTime, float searchTime, int start, int end)
211 throws IOException {
212
213 int length = luceneHits.length();
214
215 if ((start == QueryUtil.ALL_POS) && (end == QueryUtil.ALL_POS)) {
216 start = 0;
217 end = length;
218 }
219
220 String[] queryTerms = getQueryTerms(query);
221
222 Hits subset = new HitsImpl();
223
224 if ((start > - 1) && (start <= end)) {
225 if (end > length) {
226 end = length;
227 }
228
229 int subsetTotal = end - start;
230
231 Document[] subsetDocs = new DocumentImpl[subsetTotal];
232 String[] subsetSnippets = new String[subsetTotal];
233 float[] subsetScores = new float[subsetTotal];
234
235 int j = 0;
236
237 for (int i = start; i < end; i++, j++) {
238 org.apache.lucene.document.Document doc = luceneHits.doc(i);
239
240 subsetDocs[j] = getDocument(doc);
241 subsetSnippets[j] = getSnippet(doc, query, Field.CONTENT);
242 subsetScores[j] = luceneHits.score(i);
243 }
244
245 subset.setStart(startTime);
246 subset.setSearchTime(searchTime);
247 subset.setQueryTerms(queryTerms);
248 subset.setDocs(subsetDocs);
249 subset.setLength(length);
250 subset.setSnippets(subsetSnippets);
251 subset.setScores(subsetScores);
252 }
253
254 return subset;
255 }
256
257 private static Log _log = LogFactoryUtil.getLog(
258 LuceneIndexSearcherImpl.class);
259
260 }