LuceneSearch.java
Upload User: gdxydsw
Upload Date: 2019-01-29
Package Size: 16721k
Code Size: 7k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * Copyright (c) JForum Team
  3.  * All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, 
  6.  * with or without modification, are permitted provided 
  7.  * that the following conditions are met:
  8.  * 
  9.  * 1) Redistributions of source code must retain the above 
  10.  * copyright notice, this list of conditions and the 
  11.  * following  disclaimer.
  12.  * 2)  Redistributions in binary form must reproduce the 
  13.  * above copyright notice, this list of conditions and 
  14.  * the following disclaimer in the documentation and/or 
  15.  * other materials provided with the distribution.
  16.  * 3) Neither the name of "Rafael Steil" nor 
  17.  * the names of its contributors may be used to endorse 
  18.  * or promote products derived from this software without 
  19.  * specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
  22.  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
  23.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  24.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  25.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  26.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
  27.  * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  30.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  31.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  32.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  33.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
  34.  * IN CONTRACT, STRICT LIABILITY, OR TORT 
  35.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  36.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  37.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  38.  * 
  39.  * Created on 18/07/2007 22:05:37
  40.  * 
  41.  * The JForum Project
  42.  * http://www.jforum.net
  43.  */
  44. package net.jforum.search;
  45. import java.io.IOException;
  46. import java.io.StringReader;
  47. import java.util.ArrayList;
  48. import java.util.List;
  49. import net.jforum.exceptions.SearchException;
  50. import org.apache.log4j.Logger;
  51. import org.apache.lucene.analysis.Token;
  52. import org.apache.lucene.analysis.TokenStream;
  53. import org.apache.lucene.analysis.standard.StandardAnalyzer;
  54. import org.apache.lucene.document.Document;
  55. import org.apache.lucene.index.Term;
  56. import org.apache.lucene.queryParser.QueryParser;
  57. import org.apache.lucene.search.Filter;
  58. import org.apache.lucene.search.Hits;
  59. import org.apache.lucene.search.IndexSearcher;
  60. import org.apache.lucene.search.Query;
  61. import org.apache.lucene.search.Sort;
  62. import org.apache.lucene.search.TermQuery;
  63. /**
  64.  * @author Rafael Steil
  65.  * @version $Id: LuceneSearch.java,v 1.38 2007/10/05 03:22:37 rafaelsteil Exp $
  66.  */
  67. public class LuceneSearch implements NewDocumentAdded
  68. {
  69. private static final Logger logger = Logger.getLogger(LuceneSearch.class);
  70. private IndexSearcher search;
  71. private LuceneSettings settings;
  72. private LuceneResultCollector contentCollector;
  73. public LuceneSearch(LuceneSettings settings, 
  74. LuceneResultCollector contentCollector)
  75. {
  76. this.settings = settings;
  77. this.contentCollector = contentCollector;
  78. this.openSearch();
  79. }
  80. /**
  81.  * @see net.jforum.search.NewDocumentAdded#newDocumentAdded()
  82.  */
  83. public void newDocumentAdded()
  84. {
  85. try {
  86. this.search.close();
  87. this.openSearch();
  88. }
  89. catch (Exception e) {
  90. throw new SearchException(e);
  91. }
  92. }
  93. /**
  94.  * @see net.jforum.dao.SearchDAO#search(net.jforum.search.SearchArgs)
  95.  */
  96. public SearchResult search(SearchArgs args)
  97. {
  98. return this.performSearch(args, this.contentCollector, null);
  99. }
  100. public Document findDocumentByPostId(int postId)
  101. {
  102. Document doc = null;
  103. try {
  104. Hits hit = this.search.search(new TermQuery(
  105. new Term(SearchFields.Keyword.POST_ID, String.valueOf(postId))));
  106. if (hit.length() > 0) {
  107. doc = hit.doc(0);
  108. }
  109. }
  110. catch (IOException e) {
  111. throw new SearchException(e);
  112. }
  113. return doc;
  114. }
  115. private SearchResult performSearch(SearchArgs args, LuceneResultCollector resultCollector, Filter filter)
  116. {
  117. SearchResult result;
  118. try {
  119. StringBuffer criteria = new StringBuffer(256);
  120. this.filterByForum(args, criteria);
  121. this.filterByKeywords(args, criteria);
  122. this.filterByDateRange(args, criteria);
  123. Query query = new QueryParser("", new StandardAnalyzer()).parse(criteria.toString());
  124. if (logger.isDebugEnabled()) {
  125. logger.debug("Generated query: " + query);
  126. }
  127. Hits hits = filter == null ? 
  128. this.search.search(query, this.getSorter(args))
  129. : this.search.search(query, filter, this.getSorter(args));
  130. if (hits != null && hits.length() > 0) {
  131. result = new SearchResult(resultCollector.collect(args, hits, query), hits.length());
  132. }
  133. else {
  134. result = new SearchResult(new ArrayList(), 0);
  135. }
  136. }
  137. catch (Exception e) {
  138. throw new SearchException(e);
  139. }
  140. return result;
  141. }
  142. private Sort getSorter(SearchArgs args)
  143. {
  144. Sort sort = Sort.RELEVANCE;
  145. if ("time".equals(args.getOrderBy())) {
  146. sort = new Sort(SearchFields.Keyword.POST_ID, "DESC".equals(args.getOrderDir()));
  147. }
  148. return sort;
  149. }
  150. private void filterByDateRange(SearchArgs args, StringBuffer criteria)
  151. {
  152. if (args.getFromDate() != null) {
  153. criteria.append('(')
  154. .append(SearchFields.Keyword.DATE)
  155. .append(": [")
  156. .append(this.settings.formatDateTime(args.getFromDate()))
  157. .append(" TO ")
  158. .append(this.settings.formatDateTime(args.getToDate()))
  159. .append(']')
  160. .append(')');
  161. }
  162. }
  163. private void filterByKeywords(SearchArgs args, StringBuffer criteria)
  164. {
  165. String[] keywords = this.analyzeKeywords(args.rawKeywords());
  166. for (int i = 0; i < keywords.length; i++) {
  167. if (args.shouldMatchAllKeywords()) {
  168. criteria.append(" +");
  169. }
  170. criteria.append('(')
  171. .append(SearchFields.Indexed.CONTENTS)
  172. .append(':')
  173. .append(QueryParser.escape(keywords[i]))
  174. .append(") ");
  175. }
  176. }
  177. private void filterByForum(SearchArgs args, StringBuffer criteria)
  178. {
  179. if (args.getForumId() > 0) {
  180. criteria.append("+(")
  181. .append(SearchFields.Keyword.FORUM_ID)
  182. .append(':')
  183. .append(args.getForumId())
  184. .append(") ");
  185. }
  186. }
  187. private String[] analyzeKeywords(String contents)
  188. {
  189. try {
  190. TokenStream stream = this.settings.analyzer().tokenStream("contents", new StringReader(contents));
  191. List tokens = new ArrayList();
  192. while (true) {
  193. Token token = stream.next();
  194. if (token == null) {
  195. break;
  196. }
  197. tokens.add(token.termText());
  198. }
  199. return (String[])tokens.toArray(new String[0]);
  200. }
  201. catch (IOException e) {
  202. throw new SearchException(e);
  203. }
  204. }
  205. private void openSearch()
  206. {
  207. try {
  208. this.search = new IndexSearcher(this.settings.directory());
  209. }
  210. catch (IOException e) {
  211. throw new SearchException(e.toString(), e);
  212. }
  213. }
  214. }