文档章节

接触lucene

北风刮的不认真了
 北风刮的不认真了
发布于 2014/10/30 11:01
字数 1475
阅读 40
收藏 1

lucene。。数据从数据库中获得,

所以我下面展示的代码描述的就是一个,

    1,从数据库查数据,然后把这些数据通过lucene创建索引库保存在硬盘上。

    2,从索引库查出数据。

    3,完!

package com.bjtc;

import java.io.File;     
import java.io.Reader;
import java.io.StringReader;
import java.sql.Connection;     
import java.sql.ResultSet;     
import java.sql.Statement;     
import java.util.regex.Pattern;


import org.apache.lucene.analysis.Analyzer;     
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Analyzer.TokenStreamComponents;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.pattern.PatternTokenizer;
import org.apache.lucene.document.Document;     
import org.apache.lucene.document.Field;     
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.FieldType.NumericType;
import org.apache.lucene.document.FloatField;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import com.PatternAnalyzer;

public class CreateIndex {
	static String indexpath="e:\\indextest\\index";
	static File indexFile = null; 
    Analyzer analyzer = null;  
    String brandsql="(select b.name from brand b where b.id=g.brand_id) as brandName";
    String categorySql="(select c.name from category c where c.id=g.category_id) as categroyName";
    String price ="(select max(s.price) from seller_goods s where s.goods_id=g.id) as Sprice";
    String attrSql="select * from Goods_Attr where goods_id=";
    String sql="select g.* ,"+brandsql+","+categorySql+","+price+" from goods g";
	
	public void create() throws Exception{
		//连接数据库,获得数据源
		Connection conn =DButil.getConnection();
		if(conn == null) {     
            throw new Exception("数据库连接失败");     
        }
		Statement stmt=conn.createStatement();
		ResultSet rs=stmt.executeQuery(sql);
		
		//控制创建索引,与之对应的有IndexReader来读取索引
		IndexWriter indexWriter = null;
		
		 indexFile = new File(indexpath);//创建文件夹
		 if(!indexFile.exists()) {     
            indexFile.mkdir();     
        } 
		 
		 //打开存放索引的路径
		 Directory directory = FSDirectory.open(indexFile); 
		 
		 //中文标准分词器
		 Analyzer analyzer = new SmartChineseAnalyzer(Version.LUCENE_4_9);
		 //Analyzer analyzer2= new IK_CAnalyzer();
		 IndexWriterConfig inWC=new IndexWriterConfig(Version.LUCENE_4_9, analyzer);//IndexWriterConfig
		 inWC.setOpenMode(OpenMode.CREATE);//每次生成索引时把原有索引删除,生存新的索引
		 indexWriter = new IndexWriter(directory,inWC);     
		 
		 Document doc = null;  
		 int x=0;//查看最后一共搜出多少条数据
		 System.out.println("正在创建索引ing.....");
        while(rs.next()) {     
            doc = new Document(); 
            //因为是最新版本的lucene,所以网上很多的方法不能直接使用
            //使用lucene版本是4_9的,下面的方法已经过时不用
            //Field id = new Field("id", String.valueOf(rs.getInt("id")),Field.Store.YES, Field.Index.NOT_ANALYZED);
           
            FieldType fstr=new FieldType();//定义field字段的属性
            fstr.setIndexed(true);//索引
            fstr.setStored(true);//存储
            
            //下面用的StringField,默认是不分词的!
            doc.add(new StringField("brand",rs.getString("brandName"),Field.Store.YES));
            doc.add(new StringField("category",rs.getString("categroyName"),Field.Store.YES));
            doc.add(new StringField("brief",rs.getString("brief")==null?" ":rs.getString("brief"),Field.Store.YES));
            doc.add(new StringField("type_no", rs.getString("type_no"), Field.Store.YES));
            //下面用到了FieldType使其分词并被索引。不推荐这样用
            //建议使用TextField("name", rs.getString("name"),Store.YES);
            doc.add(new Field("name", rs.getString("name"),fstr));   
            doc.add(new StringField("code",rs.getString("code"),Field.Store.YES));
            //document中可以存空串,但放null
            doc.add(new StringField("image",rs.getString("image")==null?"":rs.getString("image"),Store.YES));
            
           /* FieldType fInt=new FieldType();配置数字类型,
            fInt.setNumericType(NumericType.INT);
            fInt.setIndexed(false);不索引
            fInt.setStored(true);
            FieldType fFloat=new FieldType();
            fFloat.setNumericType(NumericType.FLOAT);
            fFloat.setIndexed(true);
            fFloat.setStored(true);*/
            doc.add(new IntField("id",rs.getInt("id"),Store.YES));
            doc.add(new FloatField("price", rs.getFloat("Sprice"),Store.YES));
            doc.add(new IntField("click_count",rs.getInt("click_count"),Store.YES));
            doc.add(new IntField("attention",rs.getInt("attention"),Store.YES));
            String strs="";
            String sqll=attrSql+rs.getInt("id");
            Statement stmt2=conn.createStatement();
    		ResultSet rs2=stmt2.executeQuery(sqll);
    		while(rs2.next()){
    			strs=rs2.getString("attr_value")+","+strs;
    		}
    		/*PatternAnalyzer pa=new PatternAnalyzer(",");此处使用的是自定义分词器,可以在doc里存TokenStream,但不可以存储
    		TokenStream ts= analyzer.tokenStream("GoodsAttr", new StringReader(strs));*/
    		rs2.close();
    		doc.add(new Field("GoodsAttr",strs,fstr));
            indexWriter.addDocument(doc);
            x++;
        }
        System.out.println("数据库查询结果   :"+x);
        System.out.println("索引创建完成!");
        indexWriter.close();  
        directory.close();
	}
	public static void main(String[] args) throws Exception{
		new CreateIndex().create();
	}
}

 建立好索引库后就开始搜索吧

package com.bjtc;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.queryparser.classic.QueryParser.Operator;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import TEST.MyAnalyzer;


public class search {
	String indexPath = "e:\\indextest\\index";
	private Integer currentPage;
	private Integer MaxPage;
	private List<Goods> list;
	
	public Integer getMaxPage() {
		return MaxPage;
	}

	public List<Goods> getList() {
		return list;
	}

	public Integer getCurrentPage() {
		return currentPage;
	}
	/**@NortherSong
	 * 多个条件精确搜索,下面有类似淘宝京东大搜索框搜索
	 * 实现了分页功能
	 * @param brand	搜索条件
	 * @param category 	搜索条件
	 * @param price	搜索条件
	 * @param attr	搜索条件
	 * @param pagerSize	一页中含数据
	 * @param currentPage	页码
	 * @throws IOException
	 * @throws ParseException
	 */
	
	public search(String brand,String category,String price,String attr,int pagerSize,int currentPage) throws IOException, ParseException{
		System.out.println("搜索条件:");
		System.out.println("category ------"+category);
		System.out.println("brand    ------"+brand);
		System.out.println("attr     ------"+attr);
		
		BooleanQuery bq=new BooleanQuery();//多个搜索条件的Query
		
		//Term是最小的搜索单元
		TermQuery termQuery1 = new TermQuery(new Term("brand", brand));
		TermQuery termQuery2 = new TermQuery(new Term("category", category));
		
		if(price.length()>0){
			String[] ps=price.split("-");
			//NumericRangeQuery.newFloatRange范围搜索
			Query q= NumericRangeQuery.newFloatRange("price", Float.valueOf(ps[0]), Float.valueOf(ps[1]), true, true);
			bq.add(q, Occur.MUST);
		}
		//Occur.MUST表示BooleanQuery中条件为并的关系,SHORLD:或
		if(null!=brand&&brand.trim().length()!=0)
			bq.add(termQuery1, Occur.MUST);
		if(null!=category&&category.trim().length()!=0)
			bq.add(termQuery2, Occur.MUST);
		if(null!=attr&&attr.trim().length()!=0)
		{
			String[] attrs = attr.split(" ");
			for(String atr:attrs){
				if(atr.length()>1){
					atr= atr.trim();
					System.out.println(attr);
					bq.add(new TermQuery(new Term("goodsAttr", atr)), Occur.MUST);
					//bq.add(q, Occur.MUST);
				}
			}
		}
		
		//同创建索引时一样,要打开存放索引的路径
		Directory d = FSDirectory.open(new File(indexPath));
		IndexReader reader = DirectoryReader.open(d);//流读取
		//对所搜索出的数据进行排序
		Sort sort= new Sort();
		//默认为false 升序
		SortField s= new SortField("price", SortField.Type.FLOAT);
		sort.setSort(s);
		
		IndexSearcher searcher = new IndexSearcher(reader);//搜索  
		//searcher.search(QUERY,FILTER过滤器,最多获取数据DOCUMENT条数,sort排序);
		TopDocs topDocs = searcher.search(bq, null, 10000,sort);
		System.out.println("符合条件的" + topDocs.totalHits + "---");
		//分页
		int begin=pagerSize*(currentPage-1);
		int end=Math.min(topDocs.scoreDocs.length, begin+pagerSize);
		
		List<Goods> list = new ArrayList<Goods>();
		Goods g = null;
		for(int i=begin;i<end;i++){
			int docSn = topDocs.scoreDocs[i].doc;
			Document doc = reader.document(docSn);
			g = new Goods();
			g.setId(Integer.parseInt(doc.get("id")));
			g.setName(doc.get("name"));
			g.setCode(doc.get("code"));
			g.setBrandName(doc.get("brand"));
			g.setCategoryName(doc.get("category"));
			g.setPrice(Float.valueOf(doc.get("price")));
			g.setS(doc.get("goodsAttr"));//z注意大小写
			list.add(g);
		}
		//用完记得关闭流~
		reader.close();
		d.close();
		this.MaxPage=topDocs.totalHits;
		this.currentPage=currentPage;
		this.list= list;
	}
	
	public  search(String queryStr,int pagerSize,int currentPage) throws IOException, ParseException {
		
	//	QueryParser qp = new QueryParser(Version.LUCENE_4_9, "goodsAttr",
	//			new PatternAnalyzer(" "));对单一的字段进行搜索 例如条件可以是“联想   G”这样,我可能搜出手机或者电脑
		MultiFieldQueryParser mp = new MultiFieldQueryParser(//搜索多个字段 例如“联想  电脑  红色”
				Version.LUCENE_4_9, new String[] {"name","brandName","categoryName"},
				new SmartChineseAnalyzer(Version.LUCENE_4_9));
		mp.setDefaultOperator(Operator.AND);//多个字段之间的关系是或还是并专业点是  &&还是||
		
		Query query= mp.parse(queryStr);
		
		Directory d = FSDirectory.open(new File(indexPath));
		IndexReader reader = DirectoryReader.open(d);
		
		Sort s= new Sort();
		//默认为false 升序
		SortField sf= new SortField("price", SortField.Type.FLOAT);
		s.setSort(sf);
		IndexSearcher searcher = new IndexSearcher(reader);

		TopDocs topDocs = searcher.search(query, null, 10000,s);
		System.out.println("符合条件的" + topDocs.totalHits + "---");
		int begin=pagerSize*(currentPage-1);
		int end=Math.min(topDocs.scoreDocs.length, begin+pagerSize);
		
		List<Goods> list = new ArrayList<Goods>();
		Goods g = null;
		for(int i=begin;i<end;i++){
			int docSn = topDocs.scoreDocs[i].doc;
			Document doc = reader.document(docSn);
			g = new Goods();
			g.setId(Integer.parseInt(doc.get("id")));
			g.setName(doc.get("name"));
			g.setCode(doc.get("code"));
			g.setBrandName(doc.get("brand"));
			g.setCategoryName(doc.get("category"));
			g.setPrice(Float.valueOf(doc.get("price")));
			g.setS(doc.get("goodsAttr"));
			list.add(g);
		}
		
		reader.close();
		d.close();
		this.MaxPage=topDocs.totalHits;
		this.currentPage=currentPage;
		this.list= list;
	}
	
	public static void main(String[] args) throws IOException, ParseException{
		search ss= new search("8.5Kg 2500W tcl", 13,1);
		for(Goods g:ss.getList()){
			System.out.println("name           "+g.getName());
			System.out.println("attr           "+g.getS());
			
		}
	}
	
}

 

本文转载自:http://song571377.iteye.com/blog/2104501

北风刮的不认真了

北风刮的不认真了

粉丝 37
博文 54
码字总数 27944
作品 1
朝阳
后端工程师
私信 提问
加载中

评论(3)

北风刮的不认真了
北风刮的不认真了 博主
@红薯。。写的真容易懂。。学习了http://git.oschina.net/oschina/search-framework
北风刮的不认真了
北风刮的不认真了 博主
嗯,就是这样。据说这样搜索会比MYSQL快。
文件会越来越大。更新操作其实跟写操作差不多。
一开始我学习从ITEYE里有个叫三劫散仙的博客了解的。你可以查一下,很全。
至于代码方法,我推荐你直接在git上,看红薯的oschina搜索框架源码http://git.oschina.net/oschina/search-framework
Java_weber
Java_weber
不错啊,看了几篇文章,都不知道这lucene是用来干嘛的,看了你的文章才知道大概的流程,原来过程是把数据库里面的数据转成文件,然后在文件里面查找。但是我现在还不清楚文档怎么更新,还有文件会不会越来越大
lucene的优化问题

我现在正在做基于lucene的搜索引擎,已经简单实现;我现在关注两个问题:1、为了便于扩展lucene现有接口或类,应该在系统中怎样架构?2、怎样优化lucene的索引创建及其检索,我刚接触不太了解...

Jcrazy
2011/09/06
656
1
在lucene中的索引的路径和索引的文件目录的路径应该怎么填??

本人刚接触lucene 在lucene中的索引的路径和索引的文件目录的路径应该怎么填??

VincentBreeze
2012/07/23
338
5
lucene eclipse下如何修改分词

第一次接触这个lucene,希望大家不要见笑。在eclipse下如何修改lucene的默认分词器。因为想对学校的网页进行索引,事先已经用heritrix对学校的网页进行了采集。但是到了lucene就不知道从何下...

lixiaofeng
2010/11/17
586
3
Lucene IKAnalyzer.parseMultiField()疑问

IKAnalyzer.parseMultiField()的用法上产生了疑问 最近接到一个关于Lucene的项目,在debug的时候发现IKAnalyzer.parseMultiField(fields, speechQuerys, flags) fields = ["name","name"] sp......

ruin
2014/11/17
983
0
tomcat部署gitblit启动变得很慢是正常的吗?在gitblit中view、blame显示二进制和乱码

linux服务器,tomcat启动速度正常,部署gitblit后lucene报错org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@/root/tomcat/apache-tomcat-8.5.38/......

二虾xx
03/13
87
0

没有更多内容

加载失败,请刷新页面

加载更多

设计模式之访问者模式

定义 Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which......

陈年之后是青葱
昨天
10
0
PhotoShop 高级应用 : 分层云彩 - 简单闪电效果

1.创建黑白渐水平渐变图层 2.选择滤镜选项卡: 渲染--->分层云彩功能 3.将滤镜-云彩效果渲染后的图层进行反相操作 【此时出现闪电效果】 6.调整色阶,使得闪电效果更明显 7.创建剪贴蒙版:色...

东方墨天
昨天
11
0
三种实现Android主界面Tab的方式

三种实现Android主界面Tab的方式 https://www.cnblogs.com/caobotao/p/5103673.html

shzwork
昨天
11
0
java8-Optional类

背景 NPE问题,100%的Java程序员都碰到,并且曾经是心中的痛。 1965年英国TonyHoare引入了Null引用,后续的设计语言包括Java都保持了这种设计。 一个例子 业务模型 Person 有车一族, 有Car...

春天springcarter
昨天
11
0
py 登录github时token以及cookie的应用

import requestsfrom bs4 import BeautifulSoup## 获取tokenr1 = requests.get('https://github.com/login')s1 = BeautifulSoup(r1.text,'html.parser')token = s1.find(name='input',......

子枫Eric
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部