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