Lucene之完整搜索实例

时间:2021-07-20 03:09:14

1、创建索引器:

package yushibujue;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.apache.lucene.analysis.cjk.CJKAnalyzer;
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.SimpleFSDirectory;
import org.apache.lucene.util.Version;

import tool.FileList;
import tool.FileText;

public class LuceneIndexer {

private JTextField jtfa;
private JButton jba;
private JTextField jtfb;
private JButton jbb;
private JButton jbc;
private static JTextArea jta;

//索引器外观类
private void createAndShowGUI(){
//设置跨平台外观感觉
String lf=UIManager.getCrossPlatformLookAndFeelClassName();

//GTK外观感觉
//String lf="com.sun.java.swing.plaf.gtk.GTKLookAndFeel";

//Sysetm外观感觉
// String lf=UIManager.getSystemLookAndFeelClassName();

//windows外观感觉
// String lf="com.sun.java.swing.plaf.WindowsLookAndFeel";


//Metal外观感觉
//String lf="javax.swing.plaf.metal.MetalLookAndFeel";

//common use
try{

UIManager.setLookAndFeel(lf);

}catch(Exception e){
JOptionPane.showMessageDialog(null,"无法设定外观感觉!");
}

//java 感觉
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame=new JFrame("YUSHIBUJUE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

final JFileChooser fc=new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

Container con=frame.getContentPane();
con.setLayout(new BorderLayout());

JPanel jpup=new JPanel();
jpup.setLayout(new GridLayout(3,2));
jtfa=new JTextField(30);
jba=new JButton("选择被索引的文件存放路径");
jba.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
int r=fc.showOpenDialog(null);
if(r==JFileChooser.APPROVE_OPTION){
jtfa.setText(fc.getSelectedFile().getPath());
jbc.setEnabled(true);
}
}
}
);

jtfb=new JTextField(30);
JButton jbb=new JButton("选择索引的存放路径");
jbb.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
int r= fc.showOpenDialog(null);
if(r==JFileChooser.APPROVE_OPTION){
jtfb.setText(fc.getSelectedFile().getPath());
jbc.setEnabled(true);
}
}

}

);

JLabel jl=new JLabel("");
jbc=new JButton("建立索引");
jbc.addActionListener(
new ActionListener(){

public void actionPerformed(ActionEvent e){
try{
LuceneIndeerTool.index(jtfa.getText(),jtfb.getText());
//jbc.setEnabled(false);
}catch(Exception ee){
ee.printStackTrace();
jbc.setEnabled(true);
JOptionPane.showMessageDialog(null, "索引创建失败!");
System.out.println(ee.getMessage());
}
}
}

);
jpup.add(jtfa);
jpup.add(jba);
jpup.add(jtfb);
jpup.add(jbb);
jpup.add(jl);
jpup.add(jbc);

jta=new JTextArea(10,60);
JScrollPane jsp=new JScrollPane(jta);
con.add(jpup,BorderLayout.NORTH);
con.add(jsp,BorderLayout.CENTER);

frame.setSize(200,100);
frame.pack();
frame.setVisible(true);

}

public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable(){

public void run(){
try{
new LuceneIndexer().createAndShowGUI();
}catch(Exception e){
JOptionPane.showMessageDialog(null, "程序加载失败!");
}
}
}

);
}

//使用内部类LuceneIndexerTool来实现索引工作,这样就可以把索引建立的情况反映在文本框里面了


static class LuceneIndeerTool{
//创建索引,被索引的文件的路径,索引的路径
public static void index(String filesPath,String indexPath)throws IOException{

//建立索引器,我采用lucene4.7写法

File path=new File(indexPath);
SimpleFSDirectory indexDir=new SimpleFSDirectory(path);//读取被索引的文件目录
CJKAnalyzer analyzer=new CJKAnalyzer(Version.LUCENE_47);//创建一个二分法分析器
IndexWriterConfig conf=new IndexWriterConfig(Version.LUCENE_47, analyzer);
IndexWriter writer=new IndexWriter(indexDir,conf);


/* Directory dir=FSDirectory.open(new File(indexPath));
Analyzer analyzer=new StandardAnalyzer();
IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_4_10_2,analyzer);
IndexWriter writer=new IndexWriter(dir,config);*/

//递归遍历文件目录来建立索引
String s[]=FileList.getFiles(filesPath);
int len=s.length;
for(int i=0;i<len;i++){
File f=new File(s[i]);
String ext=getExt(f);//获取扩展名
if(ext.equalsIgnoreCase("htm")||ext.equalsIgnoreCase("html")){
Document doc=new Document();

//filename field
String filename=f.getName();
Field field=new Field("filename",filename,Field.Store.YES,Field.Index.ANALYZED);
doc.add(field);

//uri field
String uri=f.getPath();
field=new Field("uri",uri,Field.Store.YES,Field.Index.NO);
doc.add(field);

//cdate field
Date dt=new Date(f.lastModified());
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd E");
String cdate=sdf.format(dt);
field=new Field("cdate",cdate,Field.Store.YES,Field.Index.NO);
doc.add(field);

//size field
double si=f.length();
String size="";

if(si>1024){
size=String.valueOf(Math.floor(si/1024)+"K");
}else{
size=String.valueOf(si)+"Bytes";

}
field=new Field("size",size,Field.Store.YES,Field.Index.NO);
doc.add(field);

//text field
String text=FileText.getText(f);
field=new Field("text",text,Field.Store.YES,Field.Index.ANALYZED);
doc.add(field);

//digest field
String digest="";
if(text.length()>200){
digest=text.substring(0, 200);

}else{
digest=text;
}

field=new Field("digest",digest,Field.Store.YES,Field.Index.ANALYZED);
doc.add(field);


//归入索引
writer.addDocument(doc);
jta.setText(jta.getText()+"已经归入索引: " +f+"\n");
}

}
//关闭索引器
writer.close();
JOptionPane.showMessageDialog(null, "索引建立完毕!","提示", JOptionPane.INFORMATION_MESSAGE);

}

public static String getExt(File f){
String s=f.getName();
try{
s=s.substring(s.lastIndexOf(".")+1);

}catch(Exception e){
s="";
}
return s;

}



}
















}

2、创建搜索器:

package yushibujue;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;

public class LuceneSearcher {
private JTextField jtfa;
private JButton jba;
private JTextField jtfb;
private JButton jbb;
private JButton jbc;
private static JTextArea jta;
private JTextField jtfc;
private JButton jbd;
private JButton jbe;

private void createAndShowGUI(){

//设置跨平台外观感觉
String lf=UIManager.getCrossPlatformLookAndFeelClassName();

//GTK外观感觉
//String lf="com.sun.java.swing.plaf.gtk.GTKLookAndFeel";

//Sysetm外观感觉
// String lf=UIManager.getSystemLookAndFeelClassName();

//windows外观感觉
// String lf="com.sun.java.swing.plaf.WindowsLookAndFeel";


//Metal外观感觉
//String lf="javax.swing.plaf.metal.MetalLookAndFeel";

//common use
try{
UIManager.setLookAndFeel(lf);
}catch(Exception ce){
JOptionPane.showMessageDialog(null, "无法设定外观感觉!");

}

//java feel
//java 感觉
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame=new JFrame("YUSHIBUJUE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

final JFileChooser fc=new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

Container con=frame.getContentPane();
con.setLayout(new BorderLayout());

JPanel jpup=new JPanel();
jpup.setLayout(new GridLayout(2,2));
jtfa=new JTextField(30);
jba=new JButton("选择索引的存放路径");
jba.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
int r=fc.showOpenDialog(null);
if(r==JFileChooser.APPROVE_OPTION){
jtfa.setText(fc.getSelectedFile().getPath());
}
}
}
);
jtfb=new JTextField(30);
JButton jbb=new JButton("搜索");
jbb.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
String indexPath=jtfa.getText();
String phrase=jtfb.getText();
new LuceneSearcherTool().search(phrase,indexPath);
}catch(Exception ex){
JOptionPane.showMessageDialog(null, "搜索失败","提示",JOptionPane.ERROR_MESSAGE);
}
}
}
);
jpup.add(jtfa);
jpup.add(jba);
jpup.add(jtfb);
jpup.add(jbb);

jta=new JTextArea(10,30);
JScrollPane jsp=new JScrollPane(jta);

JPanel jpdown=new JPanel();
jpdown.setLayout(new FlowLayout());
jtfc=new JTextField(35);
jbd=new JButton("设定导出路径");
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
jbd.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){
int r=fc.showOpenDialog(null);
if(r==JFileChooser.APPROVE_OPTION){
jtfc.setText(fc.getSelectedFile().getPath());
}
}

});

jbe=new JButton("导出搜索结果");
jbe.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
File f=new File(jtfc.getText());
FileWriter fw=new FileWriter(f);
PrintWriter pw=new PrintWriter(fw);
pw.write(jta.getText());
pw.flush();
pw.close();
JOptionPane.showMessageDialog(null, "写入文件成功!","提示",JOptionPane.INFORMATION_MESSAGE);
}catch(IOException ioe){
JOptionPane.showMessageDialog(null, "写入文件失败!","提示",JOptionPane.ERROR_MESSAGE);
}
}
}

);


jpdown.add(jtfc);
jpdown.add(jbd);
jpdown.add(jbe);

con.add(jpup,BorderLayout.NORTH);
con.add(jsp,BorderLayout.CENTER);
con.add(jpdown,BorderLayout.SOUTH);

frame.setSize(200,100);
frame.pack();
frame.setVisible(true);

}


public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){

public void run(){

new LuceneSearcher().createAndShowGUI();
}

});
}

static class LuceneSearcherTool{
//执行搜索--搜索关键词、索引的路径
public static void search(String phrase,String indexPath)throws IOException{
//建立索引器
IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(new File(indexPath))));

//搜索text字段
Term t=new Term("text",phrase);

//生成Query对象
TermQuery query=new TermQuery(t);
TopDocs topDocs=searcher.search(query,20);

ScoreDoc[] scoreDocs=topDocs.scoreDocs;
jta.setText("检索到的记录数量:"+topDocs.totalHits+"\n");
jta.setText(jta.getText()+"*******************"+"\n\n");
System.out.println("查询结果总数:"+topDocs.totalHits+"最大的评分:"+topDocs.getMaxScore());
for(int i=0;i<scoreDocs.length;i++){
int doc=scoreDocs[i].doc;
Document document = searcher.doc(doc);
if(document==null){
continue;
}

//获得filename字段,此处采用了强制转换(try)
Field field=(Field) document.getField("filename");
String filename=field.stringValue();

//uri字段
field=(Field) document.getField("uri");
String uri=field.stringValue();

//cdate字段
field=(Field) document.getField("cdate");
String cdate =field.stringValue();

//digest 字段
field=(Field) document.getField("digest");
String digest=field.stringValue();

StringBuffer sb=new StringBuffer();
sb.append("URI:"+uri+"\n");
sb.append("filename:"+filename+"\n");
sb.append("cdate:"+cdate+"\n");
sb.append("digest:"+digest+"\n");
sb.append("-------------------"+"\n");

jta.setText(jta.getText()+sb.toString());








/* System.out.println("content:"+document.get("content"));
System.out.println("id:" + scoreDocs[i].doc + " scors:" + scoreDocs[i].score+"---index--"+scoreDocs[i].shardIndex);
*/
}

}
}

}

效果图:

索引器:

Lucene之完整搜索实例


搜索器:

Lucene之完整搜索实例