基于Lucene5.4的本地文件搜索系统
来源:互联网 发布:java spring rmi 编辑:程序博客网 时间:2024/04/27 20:13
利用lucene5.4的API完成一个本地文件的搜索系统,并部署到tomcat上,最终界面如下:
开发工具: IntelliJ IDEA 15
版本:java1.7
在Mac Os与 Windows 下均可使用。
IntelliJ 上部署 tomcat 项目可以参考下面链接:
IntelliJ 上新建 javaweb 项目并部署 tomcat
整个程序包含3大部分内容:界面、建立索引及查询内容。
1、界面
由上图所示,整个界面可以分为建立索引和查询文档两个部分组成。查询文档部分又可以细分为,输入部分和结果显示部分。
界面文件jsp部分代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><style type="text/css"> .button { width:60px; height:30px; border: 1px solid darkgray; border-radius: 10px; margin-bottom: 10px; margin-top: 10px; } .div { width: 50%; float: left; margin-left: 25%; border:2px solid gray; margin-bottom: 20px; border-radius: 10px; } .input { width: 45%; height: 30px; margin-bottom: 10px; margin-top: 10px; } .index_btn{ width:60px; height:30px; border: 1px solid darkgray; border-radius: 10px; margin-top: 20%; }</style> <head> <title>SearchSystem</title> </head> <body><div class="div"> <div style="float: left;width: 70%"> <label style="margin-left: 15px;margin-top: 10px">文档路径 :</label> <input type="text" id="DocPath" class="input"><br> <label style="margin-left: 15px;margin-top: 10px;margin-bottom: 10px"> 索引路径 :</label> <input type="text"class="input" id="IndexPath"> </div> <div style="float:left;width: 30%"> <input type="button" class="index_btn" value="建立索引" style="float: right;margin-right: 50%" onclick="CreateIndex()"><br> </div></div><div class="div"> <label style="margin-left: 15px;margin-top: 10px">查询关键字 :</label> <input type="text" id="QueryString" style="width: 30%;height: 30px;margin-bottom: 10px;margin-top: 10px;"> <input type="button" class="button" value="查询" style="float:right;margin-right: 15%;margin-top: 10px" onclick="Search_Files()"><br> <label style="margin-left: 15px">查询结果 :</label><br> <div id="result_section" style="margin-left: 15px"></div> <div style="margin-bottom: 10px; margin-top: 10px"> <div id="page_item"style="float: left"> <label style="font-size: smaller;margin-left: 15px;margin-top: 10px;margin-bottom: 40px">每页显示:</label> <select id="per_page" onchange="change_page(0)"> <option value="3">3</option> <option value="5" selected="selected">5</option> <option value="10">10</option> </select> </div> <div id = "page_section" style="font-size: smaller;margin-top: 10px; margin-left: 50%" >*/*页</div> </div> <div style="margin-top: 20px"> <input type="button" class="button" value="首页" style="margin-left: 10%" onclick="change_page(0)"> <input type="button" class="button" value="上一页" style="margin-left: 12%" onclick="change_page(1)"> <input type="button" class="button" value="下一页" style="margin-left: 12%"onclick="change_page(2)"> <input type="button" class="button" value="尾页" style="margin-left: 12%" onclick="change_page(3)"> </div> </div> </body></html>
完成了界面控件的部署之后,就可以进行后台代码的部署了。
注:对界面控件的事件绑定将在后面部分进行详述。
2、创建索引
Lucene 建立索引的主要步骤:创建索引分析器(Analyser) -> 创建索引生成器(IndexWriter) -> 构建Document –> 建立索引 -> 索引关闭。
主要代码如下:
import java.io.File;import java.io.IOException;import java.nio.file.Paths;import java.util.Date;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.store.Directory;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.document.StringField;import org.apache.lucene.document.TextField;import org.apache.lucene.store.FSDirectory;public class CreateIndex { public CreateIndex(){} public static void CreateIndexPath(String DocPath, String IndexPath) throws Exception { Date start = new Date(); deleteDir(new File(IndexPath)); try { Directory index_dir = FSDirectory.open(Paths.get(IndexPath)); Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig iwc = new IndexWriterConfig(analyzer); IndexWriter writer = new IndexWriter(index_dir, iwc); File docFile = new File(DocPath); indexDoc(writer,docFile); Date end = new Date(); System.out.println(end.getTime() - start.getTime() + " total milliseconds"); writer.close(); }catch(IOException e){ System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); e.printStackTrace(); } } /* 索引添加文档 */ private static void indexDoc(IndexWriter writer, File file)throws Exception{ try { for (File f:file.listFiles()) { Document document = new Document(); // System.out.println(f.getPath()); Field FieldPath = new StringField("path",f.getPath(), Field.Store.YES); document.add(FieldPath); // Field FieldContent = new TextField("content",new FileReader(f)); Field FieldContent = new TextField("content", com.utils.FileReader.readFile(f), Field.Store.YES); document.add(FieldContent); //System.out.println(f.getName()); Field FieldName = new StringField("name", f.getName(), Field.Store.YES); document.add(FieldName); writer.addDocument(document); } } catch (Exception e) { e.printStackTrace(); } } //删除索引 private static void deleteDir(File dir) { try { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { deleteDir(new File(dir, children[i])); } } dir.delete(); //System.out.println("delete"); }catch (Exception e) { e.printStackTrace(); } }}
创建索引的过程中,采用的是标准分词器
Analyzer analyzer = new StandardAnalyzer();
标准分词器采用一元分词,对每个字都会进行分词处理,是最简单的分词器。当然也可以根据自己的需求选择其他的分词器,这里就不做详细描述了。
对于索引的建立,这里根据需要提取三类内容,分别是路径(path)、内容(content)和名称(name):
Field FieldPath = new StringField("path",f.getPath(), Field.Store.YES); Field FieldContent = new TextField("content", com.utils.FileReader.readFile(f), Field.Store.YES); Field FieldName = new StringField("name", f.getName(), Field.Store.YES);
为了提取不同格式文件的内容,我单独写了个类FileReader,主要利用POI等API来实现这样的功能,具体代码将在下一节详述。
3、读取不同格式文件内容
要读取word,PDF等格式的文件内容,需要导入一下几个jar包:
1、poi-3.8-20120326.jar
2、poi-excelant-3.8-20120326.jar
3、poi-ooxml-3.8-20120326.jar
4、poi-ooxml-schemas-3.8-20120326.jar
5、poi-scratchpad-3.8-20120326.jar
6、dom4j-1.6.1.jar
7、poi-examples-3.8-20120326.jar
8、fontbox-1.8.10.jar
9、pdfbox-1.8.10.jar
具体代码如下:
package com.utils;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.*;import javax.activation.MimetypesFileTypeMap;import javax.swing.text.BadLocationException;import javax.swing.text.DefaultStyledDocument;import javax.swing.text.rtf.RTFEditorKit;import org.apache.poi.hslf.extractor.PowerPointExtractor;import org.apache.poi.hssf.usermodel.HSSFCell;import org.apache.poi.hssf.usermodel.HSSFRow;import org.apache.poi.hssf.usermodel.HSSFSheet;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.hwpf.extractor.WordExtractor;import org.dom4j.Element;import org.dom4j.Node;import org.dom4j.io.SAXReader;import org.apache.pdfbox.cos.COSDocument;import org.apache.pdfbox.pdfparser.PDFParser;import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.util.PDFTextStripper;import org.jsoup.Jsoup;/** * Created by chenzheng on 1/3/16. */public class FileReader { private static MimetypesFileTypeMap MIME_TYPE_MAP = new MimetypesFileTypeMap(); static { MIME_TYPE_MAP.addMimeTypes("1 txt"); MIME_TYPE_MAP.addMimeTypes("2 doc"); MIME_TYPE_MAP.addMimeTypes("2 docx"); MIME_TYPE_MAP.addMimeTypes("3 xls"); MIME_TYPE_MAP.addMimeTypes("3 xlsx"); MIME_TYPE_MAP.addMimeTypes("4 html"); MIME_TYPE_MAP.addMimeTypes("4 htm"); MIME_TYPE_MAP.addMimeTypes("5 pdf"); MIME_TYPE_MAP.addMimeTypes("6 rtf"); MIME_TYPE_MAP.addMimeTypes("7 ppt"); MIME_TYPE_MAP.addMimeTypes("8 xml"); } public static String readFile(File file) { String result = ""; try { int type = Integer.parseInt(MIME_TYPE_MAP.getContentType(file)); switch (type) { case 1: result = getTextFromTxt(file); break; case 2: result = getTextFromWord(file); break; case 3: result = getTextFromExcel(file); break; case 4: result = getTextFromHtml(file); break; case 5: result = getTextFromPdf(file); break; case 6: result = getTextFromRtf(file); break; case 7: result = getTextFromPpt(file); break; case 8: result = getTextFromXml(file); } } catch (Exception e) { } return result; } public static String getTextFromWord(File file) { String result = null; try { FileInputStream fis = new FileInputStream(file); WordExtractor wordExtractor = new WordExtractor(fis); result = wordExtractor.getText(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; } public static String getTextFromExcel(File file) { StringBuffer buff = new StringBuffer(); try { HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(file)); for (int numSheets = 0; numSheets < wb.getNumberOfSheets(); numSheets++) { if (null != wb.getSheetAt(numSheets)) { HSSFSheet aSheet = wb.getSheetAt(numSheets); for (int rowNumOfSheet = 0; rowNumOfSheet <= aSheet .getLastRowNum(); rowNumOfSheet++) { if (null != aSheet.getRow(rowNumOfSheet)) { HSSFRow aRow = aSheet.getRow(rowNumOfSheet); for (int cellNumOfRow = 0; cellNumOfRow <= aRow .getLastCellNum(); cellNumOfRow++) { if (null != aRow.getCell(cellNumOfRow)) { HSSFCell aCell = aRow.getCell(cellNumOfRow); switch (aCell.getCellType()) { case HSSFCell.CELL_TYPE_FORMULA: break; case HSSFCell.CELL_TYPE_NUMERIC: buff.append(aCell.getNumericCellValue()) .append('\t'); break; case HSSFCell.CELL_TYPE_STRING: buff.append(aCell.getStringCellValue()) .append('\t'); break; } } } buff.append('\n'); } } } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return buff.toString(); } public static String getTextFromPdf(File file)throws Exception{ String result = null; FileInputStream is = null; //PDDocument document = null; COSDocument document = null; try { is = new FileInputStream(file); PDFParser parser = new PDFParser(is); parser.parse(); document = parser.getDocument(); PDFTextStripper stripper = new PDFTextStripper(); //result = stripper.getText(document); result =stripper.getText(new PDDocument(document)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); }finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (document != null) { try { document.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } public static String getTextFromTxt(File file) throws Exception{ StringBuffer sb=new StringBuffer(); FileInputStream fis=null; fis=new FileInputStream(file); byte [] by=new byte[1024]; int len= -1; while((len=fis.read(by))!=-1) sb.append(new String(by,0,len)); if(fis!=null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public static String getTextFromRtf(File file) { String result = null; try { DefaultStyledDocument styledDoc = new DefaultStyledDocument(); InputStream is = new FileInputStream(file); new RTFEditorKit().read(is, styledDoc, 0); result = new String(styledDoc.getText(0, styledDoc.getLength()) .getBytes("ISO8859_1")); } catch (IOException e) { e.printStackTrace(); } catch (BadLocationException e) { e.printStackTrace(); } return result; } private static String getTextFromHtml(File file) throws Exception{ String string=null; string=Jsoup.parse(file,"GBK").text(); return string; } public static String getTextFromXml(File file) throws Exception{ StringBuilder sb=new StringBuilder(); SAXReader reader = new SAXReader(); org.dom4j.Document doc = reader.read(file); Element rootElem = doc.getRootElement(); getChildNodes(rootElem,sb); return sb.toString(); } private static void getChildNodes(Element elem,StringBuilder sb){ String text=elem.getText().trim(); if(text.length()!=0){ sb.append(text+" "); }else{ Iterator<Node> it = elem.nodeIterator(); while(it.hasNext()){ Node node = it.next(); if(node instanceof Element){ Element el = (Element)node; getChildNodes(el,sb); } } } } public static String getTextFromPpt(File file) throws Exception{ String s = null; InputStream is=new FileInputStream(file); PowerPointExtractor ppe=new PowerPointExtractor(is); s=ppe.getText(); is.close(); return s; } @SuppressWarnings("resource") public static String readHtml(File file) { BufferedReader br=null; StringBuffer sb = new StringBuffer(); try { br=new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); String temp=null; while((temp=br.readLine())!=null){ sb.append(temp); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return sb.toString(); }}
4、内容查询
Lucene 基本的搜索流程:指定索引目录和关键字 -> IndexSearcher实例化 -> 生成检索Query类对象 -> 检索并生成Hits对象 -> 循环Hits对象获得结果 -> 关闭IndexSearcher 。
具体代码如下:
import java.io.IOException;import java.nio.file.Paths;import java.util.Date;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.document.Document;import org.apache.lucene.index.DirectoryReader;import org.apache.lucene.index.IndexReader;import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.queryparser.classic.ParseException;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.FSDirectory;public class SearchFiles { public SearchFiles() {} public Document[] SearchFilesResult(String IndexPath, String QueryString) throws Exception { Date start = new Date(); Document[] resDoc = null; IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(IndexPath))); IndexSearcher searcher = new IndexSearcher(reader); try { Analyzer analyzer = new StandardAnalyzer(); QueryParser parser = new MultiFieldQueryParser(new String[]{"content","path"} ,analyzer); // Query query = parser.parse(new String(QueryString.getBytes("ISO-8859-1"))); Query query = parser.parse(QueryString); System.out.println("Searching for: " + QueryString); TopDocs results = searcher.search(query, 100); ScoreDoc[] hits = results.scoreDocs; resDoc = new Document[hits.length]; for (int i = 0; i < hits.length; i++) { resDoc[i] = searcher.doc(hits[i].doc); System.out.println(resDoc[i].get("name") + "[" + resDoc[i].get("path") + "]"); } Date end = new Date(); System.out.println(end.getTime() - start.getTime() + " total milliseconds"); reader.close(); return resDoc; } catch (ParseException e) { //System.out.println("Error"); System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); e.printStackTrace(); } return resDoc; }}
查询时按内容和存储路径多重查找
QueryParser parser = new MultiFieldQueryParser(new String[]{"content","path"} ,analyzer);
也可以仅对内容进行查询:
QueryParser parser = new QueryParser(new String("content"), analyzer);
这里返回了一个Lucene Document类作为结果:
resDoc = new Document[hits.length];for (int i = 0; i < hits.length; i++) { resDoc[i] = searcher.doc(hits[i].doc); }
return resDoc;
5、数据交互与事件绑定
前后端通过AJAX与Servlet进行数据交互,jsp端代码如下,
建立索引:
<script type="text/javascript"> function CreateIndex() { var request; var url; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); } else { request = new ActiveXObject("Microsoft.XMLHTTP"); } request.onreadystatechange = function () { if (request.readyState == 4 && request.status == 200) { var res = request.responseText; if (res == 1) alert("Create Index Success!"); else alert("Please enter correct path!"); } } var DocPath = document.getElementById("DocPath").value; var IndexPath = document.getElementById("IndexPath").value; url = "indexservlet?" + "&DocPath=" + DocPath + "&IndexPath=" + IndexPath; request.open("GET", url, true); request.send(); } </script>
查询文档:
<script type="text/javascript"> var xmlhttp ; var resultArray; var resultNum; function Search_Files() { var url; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = ResultPage; var IndexPath = document.getElementById("IndexPath").value; var QueryString = document.getElementById("QueryString").value; url = "searchservlet?" + "&IndexPath=" + IndexPath + "&QueryString=" + QueryString; xmlhttp.open("Post", url, true); xmlhttp.send(); } function ResultPage() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var result = xmlhttp.responseText; var result_section = document.getElementById("result_section"); if (result == 0) { alert("no_results"); result_section.innerHTML = "no_results" + "<br>"; var page_section = document.getElementById("page_section"); page_section.innerHTML = "*/*页"; }else if(result ==1) { alert("Please enter query"); } else { resultArray = eval("(" + result + ")"); resultNum = 0; for (var item in resultArray) resultNum++; change_page(0); } } }</script>
这里我们需要添加三个全局变量xmlhttp、resultArray(存放Servlet返回数据)、resultNum(查询结果数目统计),这里Servlet将数据存放在json中返回(详细代码见Servlet代码部分),通过
resultArray = eval("(" + result + ")");
将数据存入resultArray中。
Servlet代码如下,
建立索引:
import java.io.IOException;import java.io.PrintWriter;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.ServletException;public class CreateIndexServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); String DocPath = request.getParameter("DocPath").replace("//","////"); String IndexPath = request.getParameter("IndexPath").replace("//","////"); String result = "DocPath:"+DocPath+" IndexPath:"+IndexPath; PrintWriter pw = response.getWriter(); try { // System.out.println("create"); CreateIndex.CreateIndexPath(DocPath, IndexPath); System.out.println("success"); pw.println("1"); } catch (Exception e) { e.printStackTrace(); pw.println("0"); }finally { pw.close(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.print("Get"); doPost(request,response); }}
通过Servlet获取文档路径与索引路径两个参数后,执行 CreateIndex.CreateIndexPath(DocPath, IndexPath);
执行完毕后浏览器页面会给出相应的提示,如下图:
查询文档:
import org.apache.lucene.document.Document;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.xml.ws.http.HTTPException;import java.io.IOException;import java.io.PrintWriter;import net.sf.json.JSONObject;import net.sf.json.JSONException;/** * Created by chenzheng on 12/30/15. */public class SearchFilesServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException,JSONException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); String IndexPath = request.getParameter("IndexPath").replace("\\","\\\\"); String QueryString = request.getParameter("QueryString").replace("\\","\\\\"); String result = "IndexPath:" + IndexPath + " QueryString:" + QueryString; System.out.println(result); try{ SearchFiles Search_Files = new SearchFiles(); Document[] resDocs = Search_Files.SearchFilesResult(IndexPath,QueryString); if(resDocs.length > 0) { JSONObject jsonObj = new JSONObject(); int i = 0; for (Document doc:resDocs) { jsonObj.put(i, doc.get("path")); i++; } pw.println(jsonObj); } else { System.out.println("no result"); pw.println("0"); } }catch(HTTPException e){ e.printStackTrace(); pw.println("1"); }catch (JSONException e){ System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); e.printStackTrace(); pw.println("1"); }catch (Exception e) { e.printStackTrace(); pw.println("1"); }finally { pw.close(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Get"); doPost(request,response); }}
通过Servlet获取关键字与索引路径两个参数后,执行
Document[] resDocs =Search_Files.SearchFilesResult(IndexPath,QueryString);
获取搜索结果,并将结果通过json返回jsp页面,
if(resDocs.length > 0) { JSONObject jsonObj = new JSONObject(); int i = 0; for (Document doc:resDocs) { jsonObj.put(i, doc.get("path")); i++; } pw.println(jsonObj); }
在写servlet的时候我们需要在web.xml文件里编写如下代码:
<servlet> <servlet-name>CreateIndexServlet</servlet-name> <servlet-class>CreateIndexServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CreateIndexServlet</servlet-name> <url-pattern>/indexservlet</url-pattern> </servlet-mapping> <servlet> <servlet-name>SearchFilesServlet</servlet-name> <servlet-class>SearchFilesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SearchFilesServlet</servlet-name> <url-pattern>/searchservlet</url-pattern> </servlet-mapping>
只有这样在AJAX里才能将数据正确的传递到相应的Sevlet上进行处理。
页面事件绑定:
页面事件绑定除了上述的建立索引与查询结果的点击事件以外,还包括分页与显示条数的功能,主要代码如下:
var cur_Page;var sum_Page;function change_page(type) { switch (type) { case 0: cur_Page = 0; set_Page(cur_Page); break; case 1: if(cur_Page>0){ cur_Page = cur_Page -1; set_Page(cur_Page); } break; case 2: if(cur_Page <(sum_Page -1)) { cur_Page = cur_Page + 1; set_Page(cur_Page); } break; case 3: cur_Page = sum_Page -1; set_Page(cur_Page); break; } } function set_Page(page) { var per_Page = document.getElementById("per_page"); var res_per_Page; for (var j=0; j<per_Page.length; j++) { if(per_Page[j].selected == true) res_per_Page = per_Page[j].innerHTML; } if (resultNum % res_per_Page == 0) { sum_Page = parseInt(resultNum / res_per_Page); } else sum_Page = parseInt(resultNum / res_per_Page) + 1; var page_section = document.getElementById("page_section"); page_section.innerHTML = (page + 1) + "/" + sum_Page + "页"; var currentItem = page * res_per_Page; var content = ""; for (var i = 0; i < res_per_Page && currentItem + i < resultNum; i++) { content = content + resultArray[currentItem + i] + "</br>"; } var result_section = document.getElementById("result_section"); result_section.innerHTML = content; }
这里 cur_Page与 sum_Page 都是全局变量。
最终的效果如下图:
- 基于Lucene5.4的本地文件搜索系统
- Lucene5(4)修改指定索引的搜索权重
- lucene全文搜索之一:lucene的主要功能和基本结构(基于lucene5.5.3)
- Lucene5.0索引的创建与搜索
- Lucene5(5)搜索api
- lucene5--增量索引(Zoie)(近实时搜索的实现)
- lucene全文搜索之四:创建索引搜索器、6种文档搜索器实现以及搜索结果分析(结合IKAnalyzer分词器的搜索器)基于lucene5.5.3
- 搜索系统--基于Solr4.9.0的实现
- 基于codeigniter框架写的网站日志系统适配器(支持写入本地文件、数据库、远程服务器)
- lucene全文搜索之二:创建索引器(创建IKAnalyzer分词器和索引目录管理)基于lucene5.5.3
- lucene全文搜索之三:生成索引字段,创建索引文档(给索引字段加权)基于lucene5.5.3
- Lucene5 学习笔记(3) —— 重用 IndexReader 和常用的搜索方法
- Lucene5 学习笔记(3) —— 重用 IndexReader 和常用的搜索方法
- Lucene5.5对索引进行搜索
- Lucene5 一个简单的Demo
- 基于网络游戏资料数据的搜索系统的设计
- 创建访问本地文件系统的信任APPLET
- 读取系统本地文件的三个时间
- Log4j.properties 属性详解
- 修改Eclipse中项目在Apache Tomcat中的部署路径
- 关于子网掩码 和 IP
- Apache Maven 入门篇(下)
- 时钟初始化flash设置
- 基于Lucene5.4的本地文件搜索系统
- 做程序的第二年--2015年总结
- POJ 3176(动态规划:数塔问题)
- SDUT3173 有多少个连续子序列的和能被k整除
- 获取系统时间
- 简单Spring中的Quartz配置(收集)
- 数据抽取2
- WC2016 挑战NPC
- 《5》单例模式