Lucene初级教程

合集下载

lucene源码构建

lucene源码构建

Lucene是一个开源的全文搜索引擎库,它提供了强大的信息检索(IR)和全文搜索功能。

要构建Lucene源代码,您需要执行以下步骤:1. 下载Lucene源代码首先,您需要从Apache Lucene的官方网站下载Lucene源代码。

您可以在Apache Lucene的官方网站上找到最新版本的的源代码。

2. 设置开发环境在开始构建Lucene源代码之前,您需要设置Java开发环境,并确保您已经安装了JDK(Java Development Kit)。

在Windows操作系统上,您可以使用Eclipse或IntelliJ IDEA等集成开发环境(IDE)来构建Lucene源代码。

在Linux上,您可以使用命令行界面和文本编辑器来构建Lucene源代码。

3. 构建Lucene源代码在设置好开发环境之后,您可以使用Maven或Gradle等构建工具来构建Lucene源代码。

如果您使用Maven,您需要在终端中执行以下命令:```shellmvn clean install```如果您使用Gradle,您需要在终端中执行以下命令:```gradle clean build```这些命令将会编译Lucene源代码,并将其打包成JAR文件或WAR文件等可执行文件。

4. 配置环境变量为了在系统上运行Lucene,您需要将Lucene的库文件路径添加到系统的环境变量中。

在Linux上,您可以将Lucene的库文件路径添加到LD_LIBRARY_PATH环境变量中。

在Windows上,您可以将Lucene的库文件路径添加到PATH环境变量中。

完成以上步骤之后,您就可以成功地构建Lucene源代码,并将其部署到您的应用程序中。

Lucene初级教程

Lucene初级教程

Lucene初级教程2007-12-26 15:24 点击次数:0 次1 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品。

因此它并不像 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。

2 lucene的工作方式lucene提供的服务实际包含两部分:一入一出。

所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。

2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。

将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。

将索引写入存储器,存储器可以是内存或磁盘。

2.2读出流程用户提供搜索关键词,经过analyzer处理。

对处理后的关键词搜索索引找出对应的Document。

用户根据需要从找到的Document中提取需要的Field。

3 一些需要知道的概念3.1 analyzerAnalyzer是分析器,它的作用是把一个字符串按某种规则划分成一个个词语,并去除其中的无效词语,这里说的无效词语是指英文中的“of”、“the”,中文中的“的”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率。

分词的规则千变万化,但目的只有一个:按语义划分。

这点在英文中比较容易实现,因为英文本身就是以单词为单位的,已经用空格分开;而中文则必须以某种方法将连成一片的句子划分成一个个词语。

具体划分方法下面再详细介绍,这里只需了解分析器的概念即可。

3.2 document用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。

一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。

Lucene入门+实现

Lucene入门+实现

Lucene⼊门+实现Lucene简介详情见:()lucene实现原理其实⽹上很多资料表明了,lucene底层实现原理就是倒排索引(invertedindex)。

那么究竟什么是倒排索引呢?经过Lucene分词之后,它会维护⼀个类似于“词条--⽂档ID”的对应关系,当我们进⾏搜索某个词条的时候,就会得到相应的⽂档ID。

不同于传统的顺排索引根据⼀个词,知道有哪⼏篇⽂章有这个词。

图解:Lucene在搜索前⾃⾏⽣成倒排索引,相⽐数据库中like的模糊搜索效率更⾼!Lucene 核⼼API索引过程中的核⼼类1. Document⽂档:他是承载数据的实体(他可以集合信息域Field),是⼀个抽象的概念,⼀条记录经过索引之后,就是以⼀个Document的形式存储在索引⽂件中的。

2. Field:Field 索引中的每⼀个Document对象都包含⼀个或者多个不同的域(Field),域是由域名(name)和域值(value)对组成,每⼀个域都包含⼀段相应的数据信息。

3. IndexWriter:索引过程的核⼼组件。

这个类⽤于创建⼀个新的索引并且把⽂档加到已有的索引中去,也就是写⼊操作。

4. Directroy:是索引的存放位置,是个抽象类。

具体的⼦类提供特定的存储索引的地址。

(FSDirectory 将索引存放在指定的磁盘中,RAMDirectory ·将索引存放在内存中。

)5. Analyzer:分词器,在⽂本被索引之前,需要经过分词器处理,他负责从将被索引的⽂档中提取词汇单元,并剔除剩下的⽆⽤信息(停⽌词汇),分词器⼗分关键,因为不同的分词器,解析相同的⽂档结果会有很⼤的不同。

Analyzer是⼀个抽象类,是所有分词器的基类。

搜索过程中的核⼼类1. IndexSearcher :IndexSearcher 调⽤它的search⽅法,⽤于搜索IndexWriter 所创建的索引。

2. Term :Term 使⽤于搜索的⼀个基本单元。

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...自定义排序说明我们在做lucene搜索的时候,可能会需要排序功能,虽然lucene 内置了多种类型的排序,但是如果在需要先进行某些值的运算然后在排序的时候就有点显得无能为力了;要做自定义查询,我们就要研究lucene已经实现的排序功能,lucene的所有排序都是要继承FieldComparator,然后重写内部实现,这里以IntComparator为例子来查看其实现;IntComparator相关实现其类的声明为public static class IntComparator extends NumericComparator<Integer>,这里说明IntComparator接收的是Integer类型的参数,即只处理IntField的排序;IntComparator声明的参数为:[java] view plain copy1.private final int[] values;2.private int bottom; // Value of bottom of queue3.private int topValue;查看copy方法可知•values随着类初始化而初始化其长度•values用于存储NumericDocValues中读取到的内容具体实现如下:values的初始化[java] view plain copy1./**2.* Creates a new comparator based on {@link Integer#co mpare} for {@code numHits}.3.* When a document has no value for the field, {@code mi ssingValue} is substituted.4.*/5.public IntComparator(int numHits, String field, Integer mi ssingValue) {6.super(field, missingValue);7.values = new int[numHits];8.}values值填充(此为IntComparator的处理方式)[java] view plain copy1.@Override2.public void copy(int slot, int doc) {3.int v2 = (int) currentReaderValues.get(doc);4.// Test for v2 == 0 to save Bits.get method call for5.// the common case (doc has value and value is non-zero):6.if (docsWithField != null && v2 == 0 && !docsWithField. get(doc)) {7.v2 = missingValue;8.}9.10.values[slot] = v2;11.}这些实现都是类似的,我们的应用实现自定义排序的时候需要做的是对binaryDocValues或NumericDocValues的值进行计算,然后实现FieldComparator内部方法,对应IntComparator就是如上的值copy操作;然后我们需要实现compareTop、compareBottom和compare,IntComparator的实现为:[java] view plain copy1.@Override2.public int compare(int slot1, int slot2) {3.return pare(values[slot1], values[slot2]);4.}5.6.@Override7.public int compareBottom(int doc) {8.int v2 = (int) currentReaderValues.get(doc);9.// Test for v2 == 0 to save Bits.get method call for10.// the common case (doc has value and value is non-zero):11.if (docsWithField != null && v2 == 0 && !docsWithFi eld.get(doc)) {12.v2 = missingValue;13.}14.15.return pare(bottom, v2);16.}[java] view plain copy1.@Override2.public int compareTop(int doc) {3.int docValue = (int) currentReaderValues.get(doc);4.// Test for docValue == 0 to save Bits.get method call for5.// the common case (doc has value and value is non-zero):6.if (docsWithField != null && docValue == 0 && !docsWit hField.get(doc)) {7.docValue = missingValue;8.}9.return pare(topValue, docValue);10.}实现自己的FieldComparator要实现FieldComparator,需要对接收参数进行处理,定义处理值的集合,同时定义BinaryDocValues和接收的参数等,这里我写了一个通用的比较器,代码如下:[java] view plain copy1.package com.lucene.search;2.3.import java.io.IOException;4.5.import org.apache.lucene.index.BinaryDocValues;6.import org.apache.lucene.index.DocValues;7.import org.apache.lucene.index.LeafReaderContext;8.import org.apache.lucene.search.SimpleFieldComparator;9.10.import com.lucene.util.ObjectUtil;11.12./**自定义comparator13.* @author lenovo14.*15.*/16.public class SelfDefineComparator extends SimpleFie ldComparator<String> {17.private Object[] values;//定义的Object[],同IntComparator18.private Object bottom;19.private Object top;20.private String field;21.private BinaryDocValues binaryDocValues;//接收的BinaryDocValues,同IntComparator中的NumericDocValues22.private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类23.private Object[] params;//接收的参数24.25.public SelfDefineComparator(String field, int numHits, Object[] params,ObjectUtil objectUtil) {26.values = new Object[numHits];27.this.objectUtil = objectUtil;28.this.field = field;29.this.params = params;30.}31.32.@Override33.public void setBottom(int slot) {34.this.bottom = values[slot];35.}36.37.@Override38.public int compareBottom(int doc) throws IOExcepti on {39.Object distance = getValues(doc);40.return (bottom.toString()).compareTo(distance.toStrin g());41.}42.43.@Override44.public int compareTop(int doc) throws IOException {45.Object distance = getValues(doc);46.return pareTo(top,distance);47.}48.49.@Override50.public void copy(int slot, int doc) throws IOException {51.values[slot] = getValues(doc);52.}53.54./**��ȡdocID��Ӧ��value55.* @param doc56.* @return57.*/58.private Object getValues(int doc) {59.Object instance = objectUtil.getValues(doc,params,bin aryDocValues) ;60.return instance;61.}62.63.@Override64.protected void doSetNextReader(LeafReaderContext context)65.throws IOException {66.binaryDocValues = DocValues.getBinary(context.reade r(), field);//context.reader().getBinaryDocValues(field);67.}68.69.@Override70.public int compare(int slot1, int slot2) {71.return pareTo(values[slot1],values[slot2]);72.}73.@Override74.public void setTopValue(String value) {75.this.top = value;76.}77.78.@Override79.public String value(int slot) {80.return values[slot].toString();81.}82.83.}其中ObjectUtil是一个接口,定义了值处理的过程,最终是要服务于comparator的compare方法的,同时对comparator的内部compare方法进行了定义ObjectUtil接口定义如下:[java] view plain copy1.package com.lucene.util;2.3.import org.apache.lucene.index.BinaryDocValues;4.5.public interface ObjectUtil {6.7./**自定义的获取处理值的方法8.* @param doc9.* @param params10.* @param binaryDocValues11.* @return12.*/13.public abstract Object getValues(int doc, Object[] par ams, BinaryDocValues binaryDocValues) ;14.15./**compare比较器实现16.* @param object17.* @param object218.* @return19.*/20.public abstract int compareTo(Object object, Object object2);21.22.}我们不仅要提供比较器和comparator,同时还要提供接收用户输入的FiledComparatorSource[java] view plain copy1.package com.lucene.search;2.3.import java.io.IOException;4.5.import org.apache.lucene.search.FieldComparator;6.import org.apache.lucene.search.FieldComparatorSource;7.8.import com.lucene.util.ObjectUtil;9.10./**comparator用于接收用户原始输入,继承自FieldComparatorSource实现了自定义comparator的构建11.* @author lenovo12.*13.*/14.public class SelfDefineComparatorSource extends Fie ldComparatorSource {15.private Object[] params;//接收的参数16.private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类17.18.public Object[] getParams() {19.return params;20.}21.22.public void setParams(Object[] params) {23.this.params = params;24.}25.26.public ObjectUtil getObjectUtil() {27.return objectUtil;28.}29.30.public void setObjectUtil(ObjectUtil objectUtil) {31.this.objectUtil = objectUtil;32.}33.34.public SelfDefineComparatorSource(Object[] params, ObjectUtil objectUtil) {35.super();36.this.params = params;37.this.objectUtil = objectUtil;38.}39.40.@Override41.public FieldComparator<?> newComparator(String fie ldname, int numHits,42.int sortPos, boolean reversed) throws IOException {43.//实际比较由SelfDefineComparator实现44.return new SelfDefineComparator(fieldname, numHit s, params, objectUtil);45.}46.}相关测试程序,这里我们模拟一个StringComparator,对String 值进行排序[java] view plain copy1.package com.lucene.search;2.3.import org.apache.lucene.analysis.Analyzer;4.import org.apache.lucene.analysis.standard.StandardAnal yzer;5.import org.apache.lucene.document.BinaryDocValuesFiel d;6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.StringField;9.import org.apache.lucene.index.DirectoryReader;10.import org.apache.lucene.index.IndexReader;11.import org.apache.lucene.index.IndexWriter;12.import org.apache.lucene.index.IndexWriterConfig;13.import org.apache.lucene.index.IndexWriterConfig.Op enMode;14.import org.apache.lucene.index.Term;15.import org.apache.lucene.search.IndexSearcher;16.import org.apache.lucene.search.MatchAllDocsQuery;17.import org.apache.lucene.search.Query;18.import org.apache.lucene.search.ScoreDoc;19.import org.apache.lucene.search.Sort;20.import org.apache.lucene.search.SortField;21.import org.apache.lucene.search.TermQuery;22.import org.apache.lucene.search.TopDocs;23.import org.apache.lucene.search.TopFieldDocs;24.import org.apache.lucene.store.RAMDirectory;25.import org.apache.lucene.util.BytesRef;26.27.import com.lucene.util.CustomerUtil;28.import com.lucene.util.ObjectUtil;29.import com.lucene.util.StringComparaUtil;30.31./**32.*33.* @author 吴莹桂34.*35.*/36.public class SortTest {37.public static void main(String[] args) throws Exceptio n {38.RAMDirectory directory = new RAMDirectory();39.Analyzer analyzer = new StandardAnalyzer();40.IndexWriterConfig indexWriterConfig = new IndexWri terConfig(analyzer);41.indexWriterConfig.setOpenMode(OpenMode.CREATE_ OR_APPEND);42.IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);43.addDocument(indexWriter, "B");44.addDocument(indexWriter, "D");45.addDocument(indexWriter, "A");46.addDocument(indexWriter, "E");mit();48.indexWriter.close();49.IndexReader reader = DirectoryReader.open(directory) ;50.IndexSearcher searcher = new IndexSearcher(reader);51.Query query = new MatchAllDocsQuery();52.ObjectUtil util = new StringComparaUtil();53.Sort sort = new Sort(new SortField("name",new SelfD efineComparatorSource(new Object[]{},util),true));54.TopDocs topDocs = searcher.search(query, Integer.MA X_VALUE, sort);55.ScoreDoc[] docs = topDocs.scoreDocs;56.for(ScoreDoc doc : docs){57.Document document = searcher.doc(doc.doc);58.System.out.println(document.get("name"));59.}60.}61.62.private static void addDocument(IndexWriter writer,S tring name) throws Exception{63.Document document = new Document();64.document.add(new StringField("name",name,Field.Sto re.YES));65.document.add(new BinaryDocValuesField("name", new BytesRef(name.getBytes())));66.writer.addDocument(document);67.}68.}其对应的ObjectUtil实现如下:[java] view plain copy1.package com.lucene.util;2.3.import org.apache.lucene.index.BinaryDocValues;4.import org.apache.lucene.util.BytesRef;5.6.public class StringComparaUtil implements ObjectUtil {7.8.@Override9.public Object getValues(int doc, Object[] params,10.BinaryDocValues binaryDocValues) {11.BytesRef bytesRef = binaryDocValues.get(doc);12.String value = bytesRef.utf8T oString();13.return value;14.}15.16.@Override17.public int compareTo(Object object, Object object2) {18.// TODO Auto-generated method stub19.return object.toString().compareTo(object2.toString());20.}21.22.}。

lucene基础学习

lucene基础学习

搜索引擎Lucene第一章Lucene简介Lucene是apache软件基金会jakarta项目组的一个子项目,是一个开放源代码[的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。

Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

第二章lucene索引的建立的五个基础类索引的建立,Lucene 提供了五个基础类,分别是Document, Field, IndexWriter, Analyzer, Directory。

以下是他们的用途:DocumentDocument的含义为文档,在Lucene中,它代表一种逻辑文件。

Lucene本身无法对物理文件建立索引,而只能识别并处理Document的类型文件。

Lucene从Document取出相关的数据源并根据属性配置进行相应的处理。

Field对象是用来描述一个文档的某个属性的lucene中的field也具有一些特定的类型如在中,Field内部包含两个静态的内部类分别是Store和Index详细的描述了Field的属性,它们分别表示Field的储存方式和索引方式。

Store类有3个公有的静态属性::表示该Field不需要储存。

:表示该Field需要储存。

:表示使用压缩方式来保存这个Field的值。

Index有4个公有的静态属性::表示该Field不需要索引,也就是用户不需要去查找该Field的值。

:表示该Field先被分词再被索引。

TOKENIZED:表示不对该Field进行分词,但是要对他进行索引,也就是该Field会被用户查找。

:表示对该Field进行索引,但是不使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗。

Analyzer在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由Analyzer 来做的。

lucene简单使用一之文件索引

lucene简单使用一之文件索引
到此索引生成的核心都贴完了,大家领会下,下面在来看看索引的使用
Directory dir = new SimpleFSDirectory(new File(path)); List<Map<String, String>> indLs = searchTemplateList(dir,root, siteId, dirFileName); Searcher searcher = new IndexSearcher(dir); try { //分词器,与索引的分词器一致 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); //查询器 Query query = LuceneTemplate.createQuery(null, null, null, siteId, root, dirFileName, dirFileName, dirFileName, analyzer); //TODO要做翻页,收索索引 TopDocs docs = searcher.search(query, 5000); List<Map<String, String>> indLs = LuceneTemplate.getResultList(searcher, docs,0, 5000); return indLs; } finally { searcher.close(); } public static Query createQuery(String queryString, String category,String workplace, Integer siteId, String root,String filePath,String fileName,String fileContent, Analyzer analyzer) throws ParseException{ BooleanQuery bq = new BooleanQuery(); Query q; //注意我的查询器使用的是WildcardQuery,这个做like查询,配合通配符* if(StringUtils.isNotBlank(fileName)) { q = new WildcardQuery(new Term(FILENAME, "*"+fileName+"*")); bq.add(q, BooleanClause.Occur.SHOULD); } if(StringUtils.isNotBlank(filePath)) { q = new WildcardQuery(new Term(FILEPATH, "*"+filePath+"*")); bq.add(q, BooleanClause.Occur.SHOULD); }

lunce搜索引擎教程及环境配置

lunce搜索引擎教程及环境配置

全文搜索 lucene使用与优化2008-01-23 20:581 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品。

因此它并不像 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。

1.2 lucene能做什么要回答这个问题,先要了解lucene的本质。

实际上lucene的功能很单一,说到底,就是你给它若干个字符串,然后它为你提供一个全文搜索服务,告诉你你要搜索的关键词出现在哪里。

知道了这个本质,你就可以发挥想象做任何符合这个条件的事情了。

你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字段索引起来,那就不用再担心因为“%like%”而锁表了;你也可以写个自己的搜索引擎……1.3 你该不该选择lucene下面给出一些测试数据,如果你觉得可以接受,那么可以选择。

测试一:250万记录,300M左右文本,生成索引380M左右,800线程下平均处理时间300ms。

测试二:37000记录,索引数据库中的两个varchar字段,索引文件2.6M,800线程下平均处理时间1.5ms。

2 lucene的工作方式lucene提供的服务实际包含两部分:一入一出。

所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。

2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword (可选)。

将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。

将索引写入存储器,存储器可以是内存或磁盘。

2.2读出流程用户提供搜索关键词,经过analyzer处理。

对处理后的关键词搜索索引找出对应的Document。

用户根据需要从找到的Document中提取需要的Field。

Lucene教程详解

Lucene教程详解

Lucene教程详解Lucene-3.0.0配置一、Lucene开发环境配置step1.Lucene开发包下载step2.Java开发环境配置step3.Tomcat安装step4.Lucene开发环境配置解压下载的lucene-3.0.0.zip,可以看到lucene-core-3.0.0.jar和lucene-demos-3.0.0.jar这两个文件,将其解压(建议放在安装jdk的lib文件夹内),并把路径添加到环境变量的classpath。

二、Lucene开发包中Demo调试控制台应用程序step1.建立索引>java org.apache.lucene.demo.IndexFiles [C:\Java](已经存在的任意文件路径)将对C:\Java下所有文件建立索引,同时,在当前命令行位置将生成“index”文件夹。

step2.执行查询>java org.apache.lucene.demo.SearchFiles将会出现“Query:”提示符,在其后输入关键字,回车,即可得到查询结果。

Web应用程序step1.将lucene-core-3.0.0.jar和lucene-demos-3.0.0jar这两个文件复制到安装Tomcat 的\common\lib中step2.解压下载的lucene-3.0.0.zip,可以看到luceneweb.war文件。

将该文件复制到安装Tomcat的\webappsstep3.重启Tomcat服务器。

step4.建立索引>java org.apache.lucene.demo.IndexHTML -create -index [索引数据存放路径] [被索引文件路径](如:D:\lucene\temp\index D:\lucene\temp\docs)step5.打开安装Tomcat的\webapps\luceneweb\configuration.jsp文件,找到String indexLocation = "***",将"***"改为第四步中[索引数据存放路径],保存关闭。

Lucene3.0 使 用 教 程

Lucene3.0 使  用 教 程

★第一部分:概述1.我们在很多地方都可以看到搜索功能1,Windows系统中的有搜索功能:打开“我的电脑”,按“F3”就可以使用查找的功能,查找指定的文件或文件夹。

搜索的范围是整个电脑中的文件资源。

2,Eclipse中的帮助子系统:点击Help Help Contents,可以查找出相关的帮助信息。

搜索的范围是Eclipse的所有帮助文件。

3,在BBS、BLOG等系统中提供的搜索文章的功能,如这里的贴吧的例子。

搜索的范围是系统内的文章数据(都在数据库中)。

4,搜索引擎,如Baidu或Google等,可以查询到互联网中的网页、PDF、DOC、PPT、图片、视频等。

下图是使用百度搜索的效果:以上的查询功能都类似。

都是查询的文本内容,都是相同的查询方式,即找出含有指定字符串的资源,不同的只是查询范围(分别为硬盘、所有帮助文件、数据库、互联网)。

2.什么是全文检索对于搜索,按被搜索的资源类型,分为两种:可以转为文本的、多媒体类型。

我们上一节提到的搜索功能都是搜索的可以转为文本的资源(第一种)。

注意,百度或谷歌提供的音乐或视频搜索不是多媒体搜索,他们是按文件名搜索。

在智能手机上有一款音乐搜索的软件,可以让他听10秒钟的音乐,然后他就能上网找出这段音乐的名称、演奏者等信息。

这是多媒体搜索。

按搜索的方式,上一节提到的搜索功能都是不处理语义,只是找出包含指定词的所有资源(只对词进行匹配)。

下图就是显示“中国的首都是哪里”这个搜索要求对应的结果,可以看到,是没有“北京”这个结果的,结果页面都是出现了这些词的网页:全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。

全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索,我们要知道:1,只处理文本。

2,不处理语义。

3,搜索时英文不区分大小写。

4,结果列表有相关度排序。

在信息检索工具中,全文检索是最具通用性和实用性的。

Lucene搜索入门教程

Lucene搜索入门教程

Lucene搜索入门教程1.了解搜索技术1.1搜索引擎搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。

搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。

搜索引擎的原理可以看到搜索引擎的功能主要是三部分:●爬行和抓取数据(爬虫多用python来编写、但是java也能实现)●对数据对预处理(提取文字、中文分词、建立倒排索引)提供搜索功能(用户输入关键词后、去索引库搜索数据)在上述三个步骤中,java要解决的往往是后两个步骤:数据处理和搜索。

那么,我们之前学习的mysql知识也能实现数据的存储和搜索,为什么还要学新的东西呢?1.2传统数据库搜索的问题要实现类似百度的复杂搜索,或者京东的商品搜索,如果使用传统的数据库存储数据,那么会存在一系列的问题:●数据库数据单表存储能力有限,无法存储海量数据●解决大数据,可以进行分库分表。

但是分库分表会增加业务复杂度●搜索只能通过模糊匹配,效率极低●模糊搜索可能导致全表扫描,效率非常差在这里,比较棘手的其实是第二个问题:查询效率低,类似百度和京东这样的网站,对性能要求极高。

如果用户点击搜索需要很久才能拿到数据,没人愿意一直等待下去。

那么问题来了:如何才能提高模糊搜索时的效率呢?答案是:倒排索引技术1.3什么是倒排索引倒排索引是一种存储数据的方式,与传统查找有很大区别:●传统查找:采用数据按行存储,查找时逐行扫描,或者根据索引查找,然后匹配搜索条件,效率较差.概括来讲是先找到文档,然后看是否匹配.传统线性查找一个10MB的word文件,查找关键字如果在文档最后,大约3秒钟●倒排索引:首先对文档数据按照id进行索引存储,然后对文档中的数据分词,记录对词条进行索引,并记录词条在文档中出现的位置。

这样查找时只要找到了词条,就找到了对应的文档。

Lucene入门与使用

Lucene入门与使用

中国Lucene入门与使用本文主要面向具体使用,适用于已熟悉java编程的lucene初学者。

1. Lucene的简介1.1 Lucene 历史org.apache.lucene包是纯java语言的全文索引检索工具包。

Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。

目前,lucene广泛用于全文索引/检索的项目中。

lucene也被翻译成C#版本,目前发展为(不过最近好象有流产的消息)。

1.2 Lucene 原理lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。

在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。

因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。

2.Lucene的下载和配置2.1 Lucene的下载lucene在jakarta项目中的发布主页:/lucene/docs/index.html。

以下主要针对windows 用户,其它用户请在上面的地址中查找相关下载。

lucene的.jar包的下载(包括.jar和一个范例demo):/jakarta/lucene/binaries/lucene-1.4-fina l.ziplucene的源代码下载:/mirrors/apache/jakarta/lucene/source/lucene-1 .4-final-src.ziplucene的api地址:/lucene/docs/api/index.html本文使用lucene版本:lucene-1.4-final.jar。

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...这两天加班,不能兼顾博客的更新,请大家见谅。

有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引。

对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的;这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建。

对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况,这势必严重影响用户的体验;比较常见的增量索引的实现是:•设置一个定时器,定时从数据源中读取比现有索引文件中新的内容或是数据源中带有更新标示的数据。

•对数据转换成需要的document并进行索引这样做较以上的那种全删除索引然后重建的好处在于:•数据源查询扫描的数据量小•相应的更新索引的条数也少,减少了大量的IndexWriter的commit和close这些耗时操作以上解决了增量的问题,但是实时性的问题还是存在的:•索引的变更只有在IndexWriter的commit执行之后才可以体现出来那么我们怎样对实时性有个提升呢,大家都知道lucene索引可以以文件索引和内存索引两种方式存在,相较于文件索引,内存索引的执行效率要高于文件索引的构建,因为文件索引是要频繁的IO操作的;结合以上的考虑,我们采用文件索引+内存索引的形式来进行lucene 的增量更新;其实现机制如下:•定时任务扫描数据源的变更•对获得的数据源列表放在内存中•内存中的document达到数量限制的时候,以队列的方式删除内存中的索引,并将之添加到文件索引•查询的时候采用文件+内存索引联合查询的方式以达到NRT效果定时任务调度器java内置了TimerT ask,此类是可以提供定时任务的,但是有一点就是TimerTask的任务是无状态的,我们还需要对任务进行并行的设置;了解到quartz任务调度框架提供了有状态的任务StatefulJob,即在本次调度任务没有执行完毕时,下次任务不会执行;常见的我们启动一个quartz任务的方式如下:[java] view plain copy1.Date runTime = DateBuilder.evenSecondDate(new Date()) ;2.StdSchedulerFactory sf = new StdSchedulerFactory();3.Scheduler scheduler = sf.getScheduler();4.JobDetail job = JobBuilder.newJob(XXX.class).build();5.Trigger trigger = TriggerBuilder.newTrigger().startAt(runTi me).withSchedule(SimpleScheduleBuilder.simpleSchedule().withI ntervalInSeconds(3).repeatForever()).forJob(job).build();6.scheduler.scheduleJob(job, trigger);7.8.scheduler.start();</span>以上我们是设置了每三秒执行一次定时任务,而任务类是XXX 任务类通用方法这里我定义了一个XXX的父类,其定义如下:[java] view plain copy1.package com.chechong.lucene.indexcreasement;2.3.import java.util.List;4.import java.util.TimerTask;5.6.import org.apache.lucene.store.RAMDirectory;7.import org.quartz.Job;8.import org.quartz.StatefulJob;9.10./**有状态的任务:串行执行,即不允许上次执行没有完成即开始本次如果需要并行给接口改为Job即可11.* @author lenovo12.*13.*/14.public abstract class BaseInCreasementIndex implem ents StatefulJob {15./**16.* 内存索引17.*/18.private RAMDirectory ramDirectory;19.public BaseInCreasementIndex() {20.}21.public BaseInCreasementIndex(RAMDirectory ramDire ctory) {22.super();23.this.ramDirectory = ramDirectory;24.}25.26./**更新索引27.* @throws Exception28.*/29.public abstract void updateIndexData() throws Excep tion;30./**消费数据31.* @param list32.*/33.public abstract void consume(List list) throws Excepti on;34.}任务类相关实现,以下方法是获取待添加索引的数据源XXXInCreasementIndex[java] view plain copy1.@Override2.public void execute(JobExecutionContext context) throw s JobExecutionException {3.try {4.XXXInCreasementIndex index = new XXXInCreasementIn dex(Constants.XXX_INDEX_PATH, XXXDao.getInstance(), RamDir ectoryControl.getRAMDireactory());5.index.updateIndexData();6.} catch (Exception e) {7.// TODO Auto-generated catch block8.e.printStackTrace();9.}10.}[java] view plain copy1.@Override2.public void updateIndexData() throws Exception {3.int maxBeanID = SearchUtil.getLastIndexBeanID();4.System.out.println(maxBeanID);5.List<XXX> sources = XXXDao.getListInfoBefore(maxBeanID);、、6.if (sources != null && sources.size() > 0) {7.this.consume(sources);8.}9.}这里,XXX代表我们要获取数据的实体类对象consume方法主要是做两件事:•数据存放到内存索引•判断内存索引数量,超出限制的话以队列方式取出超出的数量,并将之存放到文件索引[java] view plain copy1.@Override2.public void consume(List list) throws Exception {3.IndexWriter writer = RamDirectoryControl.getRAMIndex Writer();4.RamDirectoryControl.consume(writer,list);5.}上边我们将内存索引和队列的实现放在了RamDirectoryControl 中内存索引控制器首先我们对内存索引的IndexWriter进行初始化,在初始化的时候需要注意先执行一次commit,否则会提示no segments的异常[java] view plain copy1.private static IndexWriter ramIndexWriter;2.private static RAMDirectory directory;3.static{4.directory = new RAMDirectory();5.try {6.ramIndexWriter = getRAMIndexWriter();7.} catch (Exception e) {8.// TODO Auto-generated catch block9.e.printStackTrace();10.}11.}12.public static RAMDirectory getRAMDireactory(){13.return directory;14.}15.public static IndexSearcher getIndexSearcher() throw s IOException{16.IndexReader reader = null;17.IndexSearcher searcher = null;18.try {19.reader = DirectoryReader.open(directory);20.} catch (IOException e) {21. e.printStackTrace();22.}23.searcher = new IndexSearcher(reader);24.return searcher;25.}26./**单例模式获取ramIndexWriter27.* @return28.* @throws Exception29.*/30.public static IndexWriter getRAMIndexWriter() throw s Exception{31.if(ramIndexWriter == null){32.synchronized (IndexWriter.class) {33.Analyzer analyzer = new IKAnalyzer();34.IndexWriterConfig iwConfig = new IndexWriterConfig (analyzer);35.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);36.try {37.ramIndexWriter = new IndexWriter(directory, iwConfig);mit();39.ramIndexWriter.close();40.iwConfig = new IndexWriterConfig(analyzer);41.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);42.ramIndexWriter = new IndexWriter(directory, iwConfig);43.} catch (IOException e) {44.// TODO Auto-generated catch block45. e.printStackTrace();46.}47.}48.}49.50.return ramIndexWriter;51.}定义一个获取内存索引中数据条数的方法[java] view plain copy1./**根据查询器、查询条件、每页数、排序条件进行查询2.* @param query 查询条件3.* @param first 起始值4.* @param max 最大值5.* @param sort 排序条件6.* @return7.*/8.public static TopDocs getScoreDocsByPerPageAndSortFi eld(IndexSearcher searcher,Query query, int first,int max, Sort s ort){9.try {10.if(query == null){11.System.out.println(" Query is null return null ");12.return null;13.}14.TopFieldCollector collector = null;15.if(sort != null){16.collector = TopFieldCollector.create(sort, first+max, fal se, false, false);17.}else{18.SortField[] sortField = new SortField[1];19.sortField[0] = new SortField("createTime",SortField.Ty pe.STRING,true);20.Sort defaultSort = new Sort(sortField);21.collector = TopFieldCollector.create(defaultSort,first+ max, false, false, false);22.}23.searcher.search(query, collector);24.return collector.topDocs(first, max);25.} catch (IOException e) {26.// TODO Auto-generated catch block27.}28.return null;29.}此方法返回结果为T opDocs,我们根据TopDocs的totalHits来获取内存索引中的数据条数,以此来鉴别内存占用,防止内存溢出。

Lucene学习笔记(一)

Lucene学习笔记(一)

Lucene学习笔记(一)申明:此文章中说到的分词器就是分析器中的一种,不要理解错了。

注意:以下内容中有没有解释留待以后章节解释的有:1. writer.optimize();对索引进行优化一、Lucene基础:大纲: 1. 信息获取与搜索引擎的发展2. Lucene的历史3. 建立索引(索引库)与搜索1. 信息获取技术包含:信息的表示、存储、组织和对信息的访问方法。

信息的表示和组织是为了用户更容易的访问到需要的信息。

1.1 一般来说,信息获取的流程分为以下四步:1.1.1 获取信息之前,要构建文本数据库,即将来需要进行检索的数据(被检索的数据)1.1.2 需要建立文档的索引,通过文档索引可以检索到对应的文本数据库中对应的数据;有很多建立文档索引的方法,但是用的最多的还是"倒排索引技术",其中Lucene就是采用的这种建立文档索引的技术1.1.3 完成文档索引的建立之后就可以进行检索了,此时需要用户提供一个查询关键字,该关键字将被分析然后利用一些文本处理技术进行处理,当然也可以根据具体的需求进行一系列的处理。

1.1.4 查询关键字准备好之后,进入查询,根据查询关键字可以与文档索引中的数据得到匹配进而得到文本数据库中与匹配上的文档索引对应的数据,然后反馈给用户,当然反馈之前我们可以进行排序等处理,让最接近用户需求的信息排在最前面显示2. 搜索引擎:分为"全文搜索引擎(FullT ext Search Engine)"和"分类目录(Directory)"2.1 全文搜索引擎:通过一个叫网络机器人(Spider)或者叫网络蜘蛛(Crawlers)的软件,自动分析网络上的各种连接并且获取网页信息内容而且会按照规则加以分析整理,记入数据库。

优缺点:使用关键字和一定的语法;全文搜索引擎因为依靠网络机器人等收集数据,所以数据库的容量非常庞大,但是它的查询往往不准确。

一步一步跟我学习lucene(2)---lucene的各种Field及其排序

一步一步跟我学习lucene(2)---lucene的各种Field及其排序

一步一步跟我学习lucene(2)---lucene的各种Field及其排序Lucene的Field说明Lucene存储对象是以document为存储单元,对象中相关的属性值则存放到Field中;lucene中所有Field都是IndexableField接口的实现[html] view plain copy.apache.lucene.index.IndexableField2.3.4.Represents a single field for indexing. IndexWriter con sumes Iterable<IndexableField> as a document.IndexableField接口提供了一些方法,主要是对field相关属性的获取,包括[html] view plain copy1./** 获取field的名称 */2.public String name();[java] view plain copy1./** 获取field的类型fieldType */2.public IndexableFieldType fieldType();[java] view plain copy1./**2.*获取当前field的权重(评分值)只有Field有评分的概念,如果我们想对document进行评分值的设定必须预先对document 中对应的field值进行评分设设定*/public float boost();[java] view plain copy1./** 如果此Filed为二进制类型的,返回相应的值*/2.public BytesRef binaryValue();...[java] view plain copy1./**2.* 创建一个用户索引此Field的TokenStream3.*/4.public TokenStream tokenStream(Analyzer analyzer, To kenStream reuse) throws IOException;所有的Field均是org.apache.lucene.document.Field的子类;项目中我们常用的Field类型主要有IntField, LongField, FloatField, DoubleField, BinaryDocValuesField, NumericDocValuesField, SortedDocValuesField, StringField, TextField, StoredField.lucene常见FieldIntField 主要对int类型的字段进行存储,需要注意的是如果需要对InfField进行排序使用SortField.Type.INT来比较,如果进范围查询或过滤,需要采用NumericRangeQuery.newIntRange() LongField 主要处理Long类型的字段的存储,排序使用SortField.Type.Long,如果进行范围查询或过滤利用NumericRangeQuery.newLongRange(),LongField常用来进行时间戳的排序,保存System.currentTimeMillions() FloatField 对Float类型的字段进行存储,排序采用SortField.Type.Float,范围查询采用NumericRangeQuery.newFloatRange() BinaryDocVluesField 只存储不共享值,如果需要共享值可以用SortedDocValuesField NumericDocValuesField 用于数值类型的Field的排序(预排序),需要在要排序的field后添加一个同名的NumericDocValuesField SortedDocValuesField 用于String类型的Field的排序,需要在StringField后添加同名的SortedDocValuesField StringField 用户String类型的字段的存储,StringField是只索引不分词TextField 对String类型的字段进行存储,TextField和StringField的不同是TextField既索引又分词StoredField 存储Field的值,可以用IndexSearcher.doc和IndexReader.document来获取此Field和存储的值IntField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.IntField;9.import org.apache.lucene.document.NumericDocValue sField;10.import org.apache.lucene.index.IndexWriter;11.import org.apache.lucene.search.IndexSearcher;12.import org.apache.lucene.search.MatchAllDocsQue ry;13.import org.apache.lucene.search.Query;14.import org.apache.lucene.search.ScoreDoc;15.import org.apache.lucene.search.Sort;16.import org.apache.lucene.search.SortField;17.import org.apache.lucene.search.TopFieldDocs;18.import org.junit.Test;19.20.import com.lucene.index.IndexUtil;21.import com.lucene.search.SearchUtil;22.23.public class IntFieldTest {24./**25.* 保存一个intField26.*/27.@Test28.public void testIndexIntFieldStored() {29.Document document = new Document();30.document.add(new IntField("intValue", 30, Field.Sto re.YES));31.//要排序必须加同名的field,且类型为NumericDocValuesField32.document.add(new NumericDocValuesField("intVal ue", 30));33.Document document1 = new Document();34.document1.add(new IntField("intValue", 40, Field.St ore.YES));35.document1.add(new NumericDocValuesField("intVa lue", 40));36.IndexWriter writer = null;37.try {38.writer = IndexUtil.getIndexWriter("intFieldPath", fa lse);39.writer.addDocument(document);40.writer.addDocument(document1);41.42.} catch (IOException e) {43.// TODO Auto-generated catch block44. e.printStackTrace();45.}finally{46.try {mit();48.writer.close();49.} catch (IOException e) {50.// TODO Auto-generated catch block51. e.printStackTrace();52.}53.}54.}55./**56.* 测试intField排序57.*/58.@Test59.public void testIntFieldSort(){60.try {61.IndexSearcher searcher = SearchUtil.getIndexSearc her("intFieldPath", null);62.//构建排序字段63.SortField[] sortField = new SortField[1];64.sortField[0] = new SortField("intValue",SortField.Ty pe.INT,true);65.Sort sort = new Sort(sortField);66.//查询所有结果67.Query query = new MatchAllDocsQuery();68.TopFieldDocs docs = searcher.search(query, 2, sort) ;69.ScoreDoc[] scores = docs.scoreDocs;70.//遍历结果71.for (ScoreDoc scoreDoc : scores) {72.System.out.println(searcher.doc(scoreDoc.doc));;73.}74.//searcher.search(query, results);75.} catch (IOException e) {76.// TODO Auto-generated catch block77. e.printStackTrace();78.}79.}80.81.82.}测试排序结果如下[html] view plain copy1.Document<stored<intValue:40>>2.Document<stored<intValue:30>>如果修改NumericDocValuesField对应的值,结果会随着其值的大小而改变LongField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.import org.apache.lucene.document.Document;6.import org.apache.lucene.document.Field;7.import org.apache.lucene.document.LongField;8.import org.apache.lucene.document.NumericDocValue sField;9.import org.apache.lucene.index.IndexWriter;10.import org.apache.lucene.search.IndexSearcher;11.import org.apache.lucene.search.MatchAllDocsQue ry;12.import org.apache.lucene.search.Query;13.import org.apache.lucene.search.ScoreDoc;14.import org.apache.lucene.search.Sort;15.import org.apache.lucene.search.SortField;16.import org.apache.lucene.search.TopFieldDocs;17.import org.junit.Test;18.19.import com.lucene.index.IndexUtil;20.import com.lucene.search.SearchUtil;21.22.public class LongFieldTest {23.24./**25.* 保存一个longField26.*/27.@Test28.public void testIndexLongFieldStored() {29.Document document = new Document();30.document.add(new LongField("longValue", 50L, Field.Store.YES));31.document.add(new NumericDocValuesField("longV alue", 50L));32.Document document1 = new Document();33.document1.add(new LongField("longValue", 80L, Fi eld.Store.YES));34.document1.add(new NumericDocValuesField("long Value", 80L));35.IndexWriter writer = null;36.try {37.writer = IndexUtil.getIndexWriter("longFieldPath", false);38.writer.addDocument(document);39.writer.addDocument(document1);40.41.} catch (IOException e) {42.// TODO Auto-generated catch block43. e.printStackTrace();44.}finally{45.try {mit();47.writer.close();48.} catch (IOException e) {49.// TODO Auto-generated catch block50. e.printStackTrace();51.}52.}53.}54./**55.* 测试longField排序56.*/57.@Test58.public void testLongFieldSort(){59.try {60.IndexSearcher searcher = SearchUtil.getIndexSearc her("longFieldPath", null);61.//构建排序字段62.SortField[] sortField = new SortField[1];63.sortField[0] = new SortField("longValue",SortField.Type.LONG,true);64.Sort sort = new Sort(sortField);65.//查询所有结果66.Query query = new MatchAllDocsQuery();67.TopFieldDocs docs = searcher.search(query, 2, sort) ;68.ScoreDoc[] scores = docs.scoreDocs;69.//遍历结果70.for (ScoreDoc scoreDoc : scores) {71.//System.out.println(searcher.doc(scoreDoc.doc));;72.Document doc = searcher.doc(scoreDoc.doc);73.System.out.println(doc.getField("longValue").nume ricValue());74.}75.//searcher.search(query, results);76.} catch (IOException e) {77.// TODO Auto-generated catch block78. e.printStackTrace();79.}80.}81.}运行结果如下:[html] view plain copy1.Document<stored<longValue:80>>2.Document<stored<longValue:50>>FloatField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.import org.apache.lucene.document.Document;6.import org.apache.lucene.document.Field;7.import org.apache.lucene.document.FloatDocValuesFi eld;8.import org.apache.lucene.document.FloatField;9.import org.apache.lucene.index.IndexWriter;10.import org.apache.lucene.search.IndexSearcher;11.import org.apache.lucene.search.MatchAllDocsQue ry;12.import org.apache.lucene.search.Query;13.import org.apache.lucene.search.ScoreDoc;14.import org.apache.lucene.search.Sort;15.import org.apache.lucene.search.SortField;16.import org.apache.lucene.search.TopFieldDocs;17.import org.junit.Test;18.19.import com.lucene.index.IndexUtil;20.import com.lucene.search.SearchUtil;21.22.public class FloatFieldTest {23.24./**25.* 保存一个floatField26.*/27.@Test28.public void testIndexFloatFieldStored() {29.Document document = new Document();30.document.add(new FloatField("floatValue", 9.1f, Field.Store.YES));31.document.add(new FloatDocValuesField("floatValu e", 82.0f));32.Document document1 = new Document();33.document1.add(new FloatField("floatValue", 80.1f, Field.Store.YES));34.document1.add(new FloatDocValuesField("floatVal ue", 80.1f));35.IndexWriter writer = null;36.try {37.writer = IndexUtil.getIndexWriter("floatFieldPath", false);38.writer.addDocument(document);39.writer.addDocument(document1);40.41.} catch (IOException e) {42.// TODO Auto-generated catch block43. e.printStackTrace();44.}finally{45.try {mit();47.writer.close();48.} catch (IOException e) {49.// TODO Auto-generated catch block50. e.printStackTrace();51.}52.}53.}54./**55.* 测试intField排序56.*/57.@Test58.public void testFloatFieldSort(){59.try {60.IndexSearcher searcher = SearchUtil.getIndexSearc her("floatFieldPath", null);61.//构建排序字段62.SortField[] sortField = new SortField[1];63.sortField[0] = new SortField("floatValue",SortField. Type.FLOAT,true);64.Sort sort = new Sort(sortField);65.//查询所有结果66.Query query = new MatchAllDocsQuery();67.TopFieldDocs docs = searcher.search(query, 2, sort) ;68.ScoreDoc[] scores = docs.scoreDocs;69.//遍历结果70.for (ScoreDoc scoreDoc : scores) {71.//System.out.println(searcher.doc(scoreDoc.doc));;72.Document doc = searcher.doc(scoreDoc.doc);73.System.out.println(doc.getField("floatValue").nume ricValue());74.}75.//searcher.search(query, results);76.} catch (IOException e) {77.// TODO Auto-generated catch block78. e.printStackTrace();79.}80.}81.}结果如下:[html] view plain copy1.Document<stored<floatValue:9.1>>2.Document<stored<floatValue:80.1>>BinaryDocValuesField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.import org.apache.lucene.document.BinaryDocValuesF ield;6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.FloatDocValuesFi eld;9.import org.apache.lucene.document.FloatField;10.import org.apache.lucene.document.IntField;11.import org.apache.lucene.document.LongField;12.import org.apache.lucene.document.NumericDocVa luesField;13.import org.apache.lucene.index.IndexWriter;14.import org.apache.lucene.search.IndexSearcher;15.import org.apache.lucene.search.MatchAllDocsQue ry;16.import org.apache.lucene.search.Query;17.import org.apache.lucene.search.ScoreDoc;18.import org.apache.lucene.search.Sort;19.import org.apache.lucene.search.SortField;20.import org.apache.lucene.search.TopFieldDocs;21.import org.apache.lucene.util.BytesRef;22.import org.junit.Test;23.24.import com.lucene.index.IndexUtil;25.import com.lucene.search.SearchUtil;26.27.public class BinaryDocValuesFieldTest {28.29./**30.* 保存一个BinaryDocValuesField31.*/32.@Test33.public void testIndexLongFieldStored() {34.Document document = new Document();35.document.add(new BinaryDocValuesField("binaryV alue",new BytesRef("1234".getBytes())));36.Document document1 = new Document();37.document1.add(new BinaryDocValuesField("binary Value",new BytesRef("2345".getBytes())));38.IndexWriter writer = null;39.try {40.writer = IndexUtil.getIndexWriter("binaryValueFiel dPath", false);41.writer.addDocument(document);42.writer.addDocument(document1);43.44.} catch (IOException e) {45.// TODO Auto-generated catch block46. e.printStackTrace();47.}finally{48.try {mit();50.writer.close();51.} catch (IOException e) {52.// TODO Auto-generated catch block53. e.printStackTrace();54.}55.}56.}57./**58.* 测试BinaryDocValuesField排序59.*/60.@Test61.public void testBinaryDocValuesFieldSort(){62.try {63.IndexSearcher searcher = SearchUtil.getIndexSearc her("binaryValueFieldPath", null);64.//构建排序字段65.SortField[] sortField = new SortField[1];66.sortField[0] = new SortField("binaryValue",SortField.Type.STRING_VAL,true);67.Sort sort = new Sort(sortField);68.//查询所有结果69.Query query = new MatchAllDocsQuery();70.TopFieldDocs docs = searcher.search(query, 2, sort) ;71.ScoreDoc[] scores = docs.scoreDocs;72.//遍历结果73.for (ScoreDoc scoreDoc : scores) {74.//System.out.println(searcher.doc(scoreDoc.doc));;75.Document doc = searcher.doc(scoreDoc.doc);76.System.out.println(doc);77.//System.out.println(doc.getField("binaryValue").n umericValue());78.}79.//searcher.search(query, results);80.} catch (IOException e) {81.// TODO Auto-generated catch block82. e.printStackTrace();83.}84.}85.}运行结果:[html] view plain copy1.Document<>2.Document<>为什么这样呢,这是跟BinaryDocValuesField的特性决定的,只索引不存值!StringField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.import org.apache.lucene.document.BinaryDocValuesF ield;6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.FloatDocValuesFi eld;9.import org.apache.lucene.document.FloatField;10.import org.apache.lucene.document.IntField;11.import org.apache.lucene.document.LongField;12.import org.apache.lucene.document.NumericDocVa luesField;13.import org.apache.lucene.document.SortedDocValu esField;14.import org.apache.lucene.document.StringField;15.import org.apache.lucene.index.IndexWriter;16.import org.apache.lucene.search.IndexSearcher;17.import org.apache.lucene.search.MatchAllDocsQue ry;18.import org.apache.lucene.search.Query;19.import org.apache.lucene.search.ScoreDoc;20.import org.apache.lucene.search.Sort;21.import org.apache.lucene.search.SortField;22.import org.apache.lucene.search.TopFieldDocs;23.import org.apache.lucene.util.BytesRef;24.import org.junit.Test;25.26.import com.lucene.index.IndexUtil;27.import com.lucene.search.SearchUtil;28.29.public class StringFieldTest {30.31./**32.* 保存一个StringField34.@Test35.public void testIndexLongFieldStored() {36.Document document = new Document();37.document.add(new StringField("stringValue","1244 5", Field.Store.YES));38.document.add(new SortedDocValuesField("stringVa lue", new BytesRef("12445".getBytes())));39.Document document1 = new Document();40.document1.add(new StringField("stringValue","234 56", Field.Store.YES));41.document1.add(new SortedDocValuesField("string Value", new BytesRef("23456".getBytes())));42.IndexWriter writer = null;43.try {44.writer = IndexUtil.getIndexWriter("stringFieldPath" , false);45.writer.addDocument(document);46.writer.addDocument(document1);47.48.} catch (IOException e) {49.// TODO Auto-generated catch block50. e.printStackTrace();51.}finally{52.try {mit();54.writer.close();55.} catch (IOException e) {56.// TODO Auto-generated catch block57. e.printStackTrace();59.}60.}61./**62.* 测试StringField排序63.*/64.@Test65.public void testStringFieldSort(){66.try {67.IndexSearcher searcher = SearchUtil.getIndexSearc her("stringFieldPath", null);68.//构建排序字段69.SortField[] sortField = new SortField[1];70.sortField[0] = new SortField("stringVal",SortField.T ype.STRING,true);71.Sort sort = new Sort(sortField);72.//查询所有结果73.Query query = new MatchAllDocsQuery();74.TopFieldDocs docs = searcher.search(query, 2, sort) ;75.ScoreDoc[] scores = docs.scoreDocs;76.//遍历结果77.for (ScoreDoc scoreDoc : scores) {78.//System.out.println(searcher.doc(scoreDoc.doc));;79.Document doc = searcher.doc(scoreDoc.doc);80.System.out.println(doc);81.//System.out.println(doc.getField("binaryValue").n umericValue());82.}83.//searcher.search(query, results);84.} catch (IOException e) {85.// TODO Auto-generated catch block86. e.printStackTrace();87.}88.}89.}运行结果如下:[html] view plain copy1.Document<stored,indexed,tokenized,omitNorms,inde xOptions=DOCS<stringValue:12445>>2.Document<stored,indexed,tokenized,omitNorms,inde xOptions=DOCS<stringValue:23456>>TextField使用[java] view plain copy1.package com.lucene.field;2.3.import java.io.IOException;4.5.import org.apache.lucene.document.BinaryDocValuesF ield;6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.FloatDocValuesFi eld;9.import org.apache.lucene.document.FloatField;10.import org.apache.lucene.document.IntField;11.import org.apache.lucene.document.LongField;12.import org.apache.lucene.document.NumericDocVa luesField;13.import org.apache.lucene.document.SortedDocValu esField;14.import org.apache.lucene.document.StringField;15.import org.apache.lucene.document.TextField;16.import org.apache.lucene.index.IndexWriter;17.import org.apache.lucene.search.IndexSearcher;18.import org.apache.lucene.search.MatchAllDocsQue ry;19.import org.apache.lucene.search.Query;20.import org.apache.lucene.search.ScoreDoc;21.import org.apache.lucene.search.Sort;22.import org.apache.lucene.search.SortField;23.import org.apache.lucene.search.TopFieldDocs;24.import org.apache.lucene.util.BytesRef;25.import org.junit.Test;26.27.import com.lucene.index.IndexUtil;28.import com.lucene.search.SearchUtil;29.30.public class TextFieldTest {31.32./**33.* 保存一个StringField34.*/35.@Test36.public void testIndexLongFieldStored() {37.Document document = new Document();38.document.add(new TextField("textValue","12345", Field.Store.YES));39.document.add(new SortedDocValuesField("textValue", new BytesRef("12345".getBytes())));40.Document document1 = new Document();41.document1.add(new TextField("textValue","23456", Field.Store.YES));42.document1.add(new SortedDocValuesField("textVal ue", new BytesRef("23456".getBytes())));43.IndexWriter writer = null;44.try {45.writer = IndexUtil.getIndexWriter("textFieldPath", f alse);46.writer.addDocument(document);47.writer.addDocument(document1);48.49.} catch (IOException e) {50.// TODO Auto-generated catch block51. e.printStackTrace();52.}finally{53.try {mit();55.writer.close();56.} catch (IOException e) {57.// TODO Auto-generated catch block58. e.printStackTrace();59.}60.}61.}62./**63.* 测试StringField排序64.*/65.@Test66.public void testStringFieldSort(){67.try {68.IndexSearcher searcher = SearchUtil.getIndexSearc her("textFieldPath", null);69.//构建排序字段70.SortField[] sortField = new SortField[1];71.sortField[0] = new SortField("textValue",SortField.T ype.STRING,true);72.Sort sort = new Sort(sortField);73.//查询所有结果74.Query query = new MatchAllDocsQuery();75.TopFieldDocs docs = searcher.search(query, 2, sort) ;76.ScoreDoc[] scores = docs.scoreDocs;77.//遍历结果78.for (ScoreDoc scoreDoc : scores) {79.//System.out.println(searcher.doc(scoreDoc.doc));;80.Document doc = searcher.doc(scoreDoc.doc);81.System.out.println(doc);82.//System.out.println(doc.getField("binaryValue").n umericValue());83.}84.//searcher.search(query, results);85.} catch (IOException e) {86.// TODO Auto-generated catch block87. e.printStackTrace();88.}89.}90.}运行结果如下:[html] view plain copy1.Document<stored,indexed,tokenized<textValue:23456 >>2.Document<stored,indexed,tokenized<textValue:12345 >>源码下载地址lucene field使用源码。

JAVA LUCENE教程完整版

JAVA LUCENE教程完整版

Java Lucene in Action(简体中文版)共10部分第一部分Lucene核心1.接触Lucene2.索引3.为程序添加搜索4.分析5.高极搜索技术6.扩展搜索第二部分Lucene应用7.分析常用文档格式8.工具和扩充9.Lucene其它版本10.案例学习[序章]Lucene开始是做为私有项目。

在1997年末,因为工作不稳定,我寻找自己的一些东西来卖。

Java是比较热门的编程语言,我需要一个理由来学习它。

我已经了解如何来编写搜索软件,所以我想我可以通过用Java写搜索软件来维持生计。

所以我写了Lucene。

几年以后,在2000年,我意识到我没有销售天赋。

我对谈判许可和合同没有任何兴趣,并且我也不想雇人开一家公司。

我喜欢做软件,而不是出售它。

所以我把Lucene放在SourceForge上,看看是不是开源能让我继续我想做的。

有些人马上开始使用Lucene。

大约一年后,在2001年,Apache提出要采纳Lucene。

Lucene邮件列表中的消息每天都稳定地增长。

也有人开始贡献代码,大多是围绕Lucene的边缘补充:我依然是仅有的理解它的核心的开发者。

尽管如些,Lucene开始成为真正的合作项目。

现在,2004年,Lucene有一群积极的深刻理解其核心的开发者。

我早已不再每天作开发,这个强有力的工作组在进行实质性的增加与改进。

这些年来,Lucene已经翻译成很多其它的语言包括C++、C#、Perl和Python。

在最开始的Java和其它这些语言中,Lucene的应用比我预想的要广泛地多。

它为不同的应用(如财富100公司讨论组、商业Bug跟踪、Microsoft提供的邮件搜索和100页面范围的Web搜索引擎)提供搜索动力。

在业内,我被介绍为“Lucene人”。

很多人告诉我他们在项目中使用到Lucene。

我依然认为我只听说了使用Lucene的程序的小部分。

如果我当初只是出售它,Lucene应用得不会这么广泛。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Lucene教程2007-12-26 15:24 点击次数:0 次1 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品。

因此它并不像或者google Desktop 那么拿来就能用,它只是提供了一种工具让你能实现这些产品。

2 lucene的工作方式lucene提供的服务实际包含两部分:一入一出。

所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。

2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。

将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field 存储起来。

将索引写入存储器,存储器可以是内存或磁盘。

2.2读出流程用户提供搜索关键词,经过analyzer处理。

对处理后的关键词搜索索引找出对应的Document。

用户根据需要从找到的Document中提取需要的Field。

3 一些需要知道的概念3.1 analyzerAnalyzer是分析器,它的作用是把一个字符串按某种规则划分成一个个词语,并去除其中的无效词语,这里说的无效词语是指英文中的“of”、“the”,中文中的“的”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率。

分词的规则千变万化,但目的只有一个:按语义划分。

这点在英文中比较容易实现,因为英文本身就是以单词为单位的,已经用空格分开;而中文则必须以某种方法将连成一片的句子划分成一个个词语。

具体划分方法下面再详细介绍,这里只需了解分析器的概念即可。

3.2 document用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。

一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。

用户进行搜索,也是以Document列表的形式返回。

3.3 field一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。

Field有两个属性可选:存储和索引。

通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。

这看起来似乎有些废话,事实上对这两个属性的正确组合很重要,下面举例说明:还是以刚才的文章为例子,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为真,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为假,当需要时再直接读取文件;我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为真,索引属性设置为假。

上面的三个域涵盖了两个属性的三种组合,还有一种全为假的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。

3.4 termterm是搜索的最小单位,它表示文档的一个词语,term由两部分组成:它表示的词语和这个词语所出现的field。

3.5 tockentocken是term的一次出现,它包含trem文本和相应的起止偏移,以及一个类型字符串。

一句话中可以出现多次相同的词语,它们都用同一个term表示,但是用不同的tocken,每个tocken标记该词语出现的地方。

3.6 segment添加索引时并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个segment。

4 如何建索引4.1 最简单的能完成索引的代码片断IndexWriter writer = new IndexWriter(“/data/index/”, new StandardAnalyzer(), true); Document doc = new Document();doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED)); doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED)); writer.addDocument(doc);writer.optimize();writer.close();下面我们分析一下这段代码。

首先我们创建了一个writer,并指定存放索引的目录为“/data/index”,使用的分析器为StandardAnal yzer,第三个参数说明如果已经有索引文件在索引目录下,我们将覆盖它们。

然后我们新建一个document。

我们向document添加一个field,名字是“title”,内容是“lucene introduction”,对它进行存储并索引。

再添加一个名字是“content”的field,内容是“lucene works well”,也是存储并索引。

然后我们将这个文档添加到索引中,如果有多个文档,可以重复上面的操作,创建document并添加。

添加完所有document,我们对索引进行优化,优化主要是将多个segment合并到一个,有利于提高索引速度。

随后将writer关闭,这点很重要。

对,创建索引就这么简单!当然你可能修改上面的代码获得更具个性化的服务。

4.2 索引文本文件如果你想把纯文本文件索引起来,而不想自己将它们读入字符串创建field,你可以用下面的代码创建field:Field field = new Field("content", new FileReader(file));这里的file就是该文本文件。

该构造函数实际上是读去文件内容,并对其进行索引,但不存储。

Lucene 2 教程Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。

其功能非常的强大,api也很简单。

总得来说用Lucene来进行建立和搜索和操作数据库是差不多的(有点像),Document可以看作是数据库的一行记录,Field可以看作是数据库的字段。

用lucene实现搜索引擎就像用JDBC实现连接数据库一样简单。

Lucene2.0,它与以前广泛应用和介绍的Lucene 1.4.3并不兼容。

Lucene2.0的下载地址是/lucene/java/例子一:1、在windows系统下的的C盘,建一个名叫s的文件夹,在该文件夹里面随便建三个txt文件,随便起名啦,就叫"1.txt","2.txt"和"3.txt"啦其中1.txt的内容如下:中华人民共和国全国人民2006年而"2.txt"和"3.txt"的内容也可以随便写几写,这里懒写,就复制一个和1.txt 文件的内容一样吧2、下载lucene包,放在classpath路径中建立索引:package ;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.Date;import org.apache.lucene.analysis.Analyzer;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;/*** author lighter date 2006-8-7*/public class TextFileIndexer {public static void main(String[] args) throws Exception {/*指明要索引文件夹的位置,这里是C盘的S文件夹下*/File fileDir = new File( " c:\\s " );/*这里放索引文件的位置*/File indexDir = new File( " c:\\index " );Analyzer luceneAnalyzer = new StandardAnalyzer();IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyze r,true);File[] textFiles = fileDir.listFiles();long startTime = new Date().getTime();//增加document到索引去for ( int i = 0 ; i < textFiles.length; i ++ ) {if (textFiles[i].isFile()&& textFiles[i].getName().endsWith( " .txt " )) {System.out.println( " File " + textFiles[i].getCanonicalPath()+ " 正在被索引. " );String temp = FileReaderAll(textFiles[i].getCanonicalPath()," GBK " );System.out.println(temp);Document document = new Document();Field FieldPath = new Field( " path " , textFiles[i].getPath(),Field.Store.YES, Field.Index.NO);Field FieldBody = new Field( " body " , temp, Field.Store.YES,Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);document.add(FieldPath);document.add(FieldBody);indexWriter.addDocument(document);}}//optimize()方法是对索引进行优化indexWriter.optimize();indexWriter.close();//测试一下索引的时间long endTime = new Date().getTime();System.out.println( " 这花费了"+ (endTime - startTime)+ " 毫秒来把文档增加到索引里面去! "+ fileDir.getPath());}public static String FileReaderAll(String FileName, String charset)throws IOException {BufferedReader reader = new BufferedReader( new InputStreamRead er(new FileInputStream(FileName), charset));String line = new String();String temp = new String();while ((line = reader.readLine()) != null) {temp += line;}reader.close();return temp;}}索引的结果:File C:\s\ 1 .txt正在被索引.中华人民共和国全国人民2006年File C:\s\ 2 .txt正在被索引.中华人民共和国全国人民2006年File C:\s\ 3 .txt正在被索引.中华人民共和国全国人民2006年这花费了297 毫秒来把文档增加到索引里面去! c:\s3、建立了索引之后,查询啦....package ;import java.io.IOException;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.queryParser.ParseException;import org.apache.lucene.queryParser.QueryParser;import org.apache.lucene.search.Hits;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;public class TestQuery {public static void main(String[] args) throws IOException, ParseExc eption {Hits hits = null;String queryString = " 中华" ;Query query = null;IndexSearcher searcher = new IndexSearcher( " c:\\index " );Analyzer analyzer = new StandardAnalyzer();try{QueryParser qp = new QueryParser( " body " , analyzer);query = qp.parse(queryString);} catch (ParseException e) {}if (searcher != null) {hits = searcher.search(query);if (hits.length() > 0 ) {System.out.println( " 找到: " + hits.length() + " 个结果! " );}}}}其运行结果:找到: 3 个结果!Lucene 其实很简单的,它最主要就是做两件事:建立索引和进行搜索来看一些在lucene中使用的术语,这里并不打算作详细的介绍,只是点一下而已----因为这一个世界有一种好东西,叫搜索。

相关文档
最新文档