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