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