- 浏览: 853646 次
文章分类
- 全部博客 (365)
- java (124)
- spring mvc (21)
- spring (22)
- struts2 (6)
- jquery (27)
- javascript (24)
- mybatis/ibatis (8)
- hibernate (7)
- compass (11)
- lucene (26)
- flex (0)
- actionscript (0)
- webservice (8)
- rabbitMQ/Socket (15)
- jsp/freemaker (5)
- 数据库 (27)
- 应用服务器 (21)
- Hadoop (1)
- PowerDesigner (3)
- EJB (0)
- JPA (0)
- PHP (2)
- C# (0)
- .NET (0)
- html (2)
- xml (5)
- android (7)
- flume (1)
- zookeeper (0)
- 证书加密 (2)
- maven (1)
- redis (2)
- cas (11)
最新评论
-
zuxianghuang:
通过pom上传报错 Artifact upload faile ...
nexus上传了jar包.通过maven引用当前jar,不能取得jar的依赖 -
流年末年:
百度网盘的挂了吧???
SSO单点登录系列3:cas-server端配置认证方式实践(数据源+自定义java类认证) -
953434367:
UfgovDBUtil 是什么类
Java发HTTP POST请求(内容为xml格式) -
smilease:
帮大忙了,非常感谢
freemaker自动生成源代码 -
syd505:
十分感谢作者无私的分享,仔细阅读后很多地方得以解惑。
Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
不管怎么说,搜索都是非常重要的技术,不仅仅是操作系统集成了,很多应用软件都有搜索的功能,论坛有专门用于在论坛搜索的,互联网就有诸如像百度、谷歌之类的搜索引擎,总而言之,只要数据量稍微大一点的应用程序,都会提供搜索这个功能.
我们为什么需要Lucene?
任何的的查询功能都类似,都是对文本内容的搜索,说白了,就是找出含有指定字符串的的资源,只是查找的范围不同而已.
目前的主流搜索都是全文搜索,即根据程序扫描文章中的每一个词,为每一个词建立相应的索引,并且指明该词在文章中出现的次数和位置.当用户查询时,根据建立的索引进行查找,类似于通过字典的检索方式来查字的过程.我们做搜索,要保证几点,第一点就是要快,如果百度、谷歌搜个东西要10几秒,恐怕都没人用了吧?第二点,光快有什么?搜出来的东西完全不是自己想要的,大家通过搜索引擎找东西的时候,肯定注意到了一点,就是大家很少在2页以后还点下一页,这搜索的结果是被处理过的,把最有可能是你需要的东西放在了前面,这就是准确性,而且搜索只针对文本,不管你的关键字的语义.所以,总结一下,就是:
1.只处理文本
2.不处理语义
3.英文不区分大小写
4.结果列表有相关度排序
和数据库的搜索语句有何不同?
我们为什么需要专门对全文搜索进行描述呢?因为它可以做到select语句做不到的事情.如果我们需要在数据库里面搜索一个关键字,比如ant,就会有类似的语句:
SELECT * FROM table_name WHERE content like '%ant%'
会把planting之类的单词也搜索出来,显然就是没有意义的,没有人会喜欢这样结果.
另外数据库的搜索也并不能为结果做相关度得分,也就做不了相关度排名.搜索结果也更多的是无意的,或者是无用的.
最后一点,也很致命,数据库中的like,找得非常慢,一条记录一条记录地找,有时候简直难以忍受,而用全文检索的方式则是先在目录里面查,找到记录所在的位置,再直接定位过去.
所以select语句的弱点就是Lucene的优点,它可以解决上述的问题.
在程序中需要引入哪些包?
需要如何准备开发环境呢,哪些包是必须要有的,心里要大致有个数才行:
lucene-core-3.0.1.jar(最为核心的包,必不可少)
contrib\analyzers\common\lucene-analyzers-3.0.1.jar(用来将一段字符串以什么规则分解开来的分词器)
contrib\highlighter\lucene-highlighter-3.0.1.jar(将找到的结果高亮显示)
contrib\memory\lucene-memory-3.0.1.jar(高亮显示jar包所依赖的包)
Lucene的工作流程
我们每次使用搜索引擎的时候,右上角往往会显示用了多久,这个时间让人老是感觉不太准确,好像没那么快.这不是说搜索引擎的速度不够,有可能查询真的只用了那么点时间,但是返回的页面也是需要时间来生成的,还要在页面上加入广告之类的,这个时间可能就没有计算在内.总而言之,真正用来搜索的时间是非常短的,那么它为什么能够这么快呢?实际上,搜索的时候并不是在数据库里面进行搜索,而是在Lucene维护的索引库里面进行的,索引库包含两部分内容,一个称之为目录,这个目录里面就存有各种关键词对应数据的位置,搜索的时候上,Lucene就以某种指定的规则将你提供的关键字进行分词,然后在目录里面找,找得到的话,就返回一个编号,这个编号是唯一的,通过这个编号可以找到数据,但是数据也不是存在数据库中的.Lucene的索引库中更多的部分是用来存储数据的,这个数据是从互联网或者文件系统或者数据库中找到的,就像百度的快照一样,它只是一个缓存,给你看大致的内容,当你确定这就是你要找的内容,并且点进去的时候,才真正地去访问那个页面.搜索都是在索引库里面完成的.那么就出现了一个问题,有时候搜索到的东西,点进去发现不存在,或是已经删除了,或是已经更新了.那么就需要经常更新,或是时时更新.大致流程如下:
爬虫用来不间断的获取数据,通常刚刚发布到互联网上的数据不能立即在搜索引擎中找到,就是因为这个原因.可以指定让爬虫爬哪些类型的页面,来做垂直搜索.
索引库的CURD
一切前提都是建立在有索引的基础上,所以要先创建索引.对索引进行写的对象是IndexWriter.需要指定索引的位置,可以在文件系统中,也可以在内存中,除非保证计算机的内存每时每刻都是存在的,否则将丢失:
/**
*FSDirectory:Directory是抽象类,FSDirectory是继承它的子类.FS前缀代表文件系统(File System),指定在当前路径下建立索引的文件夹名为indexDir.
*Analyzer:分词器.以某种规则对关键字进行分词,分词的结果存进目录,用编号与数据对应,需要指定Lucene的版本号.
*IndexWriter:能够建立索引库,要给定上面两个类.这里的第三个参数表示一个索引里面最多存多少个Field,超出部分将忽略.
*MaxFieldLength.LIMITED:10000.
*/
Directory directory = FSDirectory.open(new File("./indexDir/"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
IndexWriter indexWriter = new IndexWriter(directory,analyzer,MaxFieldLength.LIMITED);
这样就能创建索引库,但是不能把对象直接存进去,需要转成Lucene需求的对象:org.apache.lucene.document.Document,Document的每一个Field都代表对象需要存储在索引库中的属性,这样在搜索的时候,可以看到数据的摘要:
/**
*用Document的add()方法增加一个属性进索引库,接收一个Field对象.
*Field对象的第一个参数:用指定的字符串创建一个Field对象.
*Field对象的第二个参数:存储的值.
*Field对象的第三个参数:是否在索引库的数据里面存储Field的值.
*Field对象的第四个参数:以何种方式对第二个参数的值进行操作(分词、不分词、不建立索引).
*/
Document doc = new Document();
Article article = (Article) obj;
doc.add(new Field("id",article.getId().toString(),Store.YES,Index.ANALYZED));
把你的对象转为Document对象就可以被IndexWriter添加到索引库中了:
indexWriter.addDocument(Document);
这样,一个完整的创建索引就完成了.
添加索引的目的就是为了有效、快捷的查询,与IndexWriter对应,Lucene为查询提供了相应的API,org.apache.lucene.search.IndexSearcher,需要给它指定索引库的目录:
Directory directory = FSDirectory.open(new File("./indexDir/"));
IndexSearcher indexSearcher = new IndexSearcher(directory);
Lucene支持多种查询方式,最常用的就是Query对象了:
/**
*提供分词器
*QueryParser:用于解析查询字符串的处理器类
*第二个参数:在哪个Field里面查找
*Query.parse:需要解析的查询字符串
*/
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
QueryParser queryParser = new QueryParser(Version.LUCENE_30,"title",analyzer);
Query query = queryParser.parse("panpan");
提供分词器一定要注意:创建索引库时的分词器要和解析时用的分词器一样.不然规则不一样,处理的关键词也不一样.很的可能找不到结果.得到Query对象之后,就可以进行查询了.要用到IndexSearcher的search()方法,这个方法需要两个参数,第一个参数就是Query对象,第二个参数是需要指定返回前多少条结果.然后返回一个TopDocs对象,返回一个对象而不是一个集合也是很好理解的,因为如果我们指定了返回前100条结果,如果结果总数大于100,我们就无法知道总共有多少条记录,也就无法完成分页.所以返回一个对象,这个对象封装了记录的总数和符合搜索条件的List集合:
/**
*得到TopDocs对象之后,可以获取它的成员变量totalHits和scoreDocs.这两个成员变量的访问权限是public的,所以可以直接访问
*/
TopDocs topDocs = indexSearcher.search(query, 100);
Integer count = topDocs.totalHits;
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
然后通过循环的方式打印出来,以验证效果是否正确:
/**
*从ScoreDoc对象里面可以获取两个东西,同样是public的访问权限:
*score:相关度得分,跟在内容中出现的次数有关
*doc:从上面那个流程图中可以得知,索引库从应用程序那里接收的是Document对象,所以返回的也是Document对象.
*DocumentUtils.docConvert():自己写的工具方法,因为很多地方都要用到双边的转换
*/
List<Article> list = new ArrayList();
for(int i = 0;i<scoreDocs.length;i++){
ScoreDoc scoreDoc = scoreDocs[i];
//浮点类型的得分
float score = scoreDoc.score;
int docID = scoreDoc.doc;
Document document = indexSearcher.doc(docID);
list.add(DocumentUtils.docConvert(document, Article.class));
}
System.out.println("总共获取了" + count + "条记录");
for(Article a: list){
System.out.print(a.getId() + " ");
System.out.print(a.getContent() + " ");
System.out.println(a.getTitle());
}
把工具方法也放上来吧:
/**
*有些东西还是写死了,其实完全可以通过反射来完成,当时没有花太多时间的结果
*/
public static <M,T> T docConvert(M obj,Class<T> clazz){
try {
T t = clazz.newInstance();
if(t instanceof Document){
Document doc = (Document) t;
Article article = (Article) obj;
doc.add(new Field("id",article.getId().toString(),Store.YES,Index.ANALYZED));
doc.add(new Field("title",article.getTitle(),Store.YES,Index.ANALYZED));
doc.add(new Field("content",article.getContent(),Store.YES,Index.ANALYZED));
return (T) doc;
}else if(t instanceof Article){
Article article = (Article) t;
Document doc = (Document) obj;
article.setId(Integer.parseInt(doc.get("id")));
article.setContent(doc.get("content"));
article.setTitle(doc.get("title"));
return (T) article;
}
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
基本的创建和查询就完成了.有几点需要注意:
•IndexWriter和IndexSearcher使用完后,要记得调用它们的close()方法
•版本号一定要选择当前使用的版本
•如果在创建索引时选择Store.NO,将不会在索引库的数据中添加内容;选择Index.NO,将不会在索引库中增加目录
•目录和分词器都要匹配,不然找不到结果.更好的做好是在一个工具类中声明为static,初始化一次就行了
接下来考虑删除索引,为什么不是先更新呢?因为删除也是更新的一部分.还是需要用到IndexWriter类,有两种方式可以删除,第一种就是使用Term类,第二种就是将满足搜索条件的删除:
/**
*Term类也是用来搜索的,构造函数的意思是:在哪个Field里面查哪个关键词
*然后调用IndexWriter的deleteDocument()方法删除包含指定Term的Document
*/
IndexWriter indexWriter = null;
Term term = new Term("title","panpan");
indexWriter = new IndexWriter(Configuration.directory,Configuration.analyzer,MaxFieldLength.LIMITED);
indexWriter.deleteDocuments(term);
再来就是更新,为什么把更新放在最后?因为更新操作需要较高的代价,因为文档修改后,即使是很小的修改,就可能会造成文档中的很多关键词的位置都发生变化,这就需要频繁的读取和修改记录,这种代价是相当高的.因此,一般不进行真正的更新操作,而是使用"先删除,再创建"的策略代替更新操作:
/**
*最后一句话,相当于:
indexWriter.deleteDocuments(term);
indexWriter.addDocument(doc);
先删除,再创建!
*/
IndexWriter indexWriter = null;
Article article = new Article();
article.setContent("This is the updated content!");
article.setId(1);
article.setTitle("panpan");
Term term = new Term("id",article.getId().toString());
indexWriter = new IndexWriter(Configuration.directory,Configuration.analyzer,MaxFieldLength.LIMITED);
indexWriter.updateDocument(term, DocumentUtils.docConvert(article, Document.class));
--------------------------------------------------------------------------------
基本的CURD就到此结束了.但是有些问题没有解决,比如搜索时以上代码只能在一个Field里面进行搜索,如果我要在title和content里面同时进行搜索就不行,搜索两次?太无聊了.lucene当然有相应的解决办法,比如使用QueryParser的子类:MultiFieldQueryParser.从这个名字就猜到是专用来做多Field搜索的:
/**
*接收一个String数组也是可以理解的.
*/
String[] fields = {"title","content"};
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30,fields,Configuration.analyzer);
Query query = queryParser.parse("love");
如果稍微留心就可以注意到,索引库的文件不是一层不变的,cfs类型的文件在不停的有规律地增加,这个文件多了以后,会影响到搜索的效率,因为它要打开多个文件,所以我们又要想办法让它合并成一个文件:
indexWriter.addDocument(DocumentUtils.docConvert(article, Document.class));
indexWriter.optimize();
这是手动优化的方法,IndexWriter在关闭时候会自动调用commit()方法,这个方法会把索引真正的写到硬盘上去,也就是说每一次对索引库进行操作,都会生成一个索引文件.手动优化毕竟不太方便,那是否有自动优化的操作呢?答案是肯定的:
indexWriter.addDocument(DocumentUtils.docConvert(article, Document.class));
//手动优化 合并文件
//indexWriter.optimize();
//自动优化 合并文件
indexWriter.setMergeFactor(5);
设置合并因子即可,这里又有两点需要注意:
1.默认合并因子为10,也就是说cfs文件达到10个,Lucene就会自动合并
2.设置合并因子的代码一定要在操作IndexWriter的时候进行,并且是每一次操作的时候都要进行,它需要不停的判断
接着下一个问题,更新索引库实际上就是更新硬盘上的目录,每次更新或者创建新的索引都对硬盘进行操作,大家肯定都知道效率不高,但是索引库一定是要放在硬盘上的,不能随着程序的结束而结束,那么就要找个既能存储在硬盘上,又能保证效率的方法,比如程序启动的时候从硬盘加载索引库,而后一切操作都是针对内存中的索引库进行操作,在程序结束的时候把内存中的索引库存储在硬盘上去.这样就能解决这个不是问题的问题:
public void updateRAMIndex(){
//RAMDirectory是Directory的子类,将在内存区保留一段缓存
RAMDirectory ram = null;
IndexWriter indexWriter = null;
try {
//将指定目录中的索引加载到内存中来
ram = new RAMDirectory(Configuration.directory);
//第一个参数决定了这是一个操作内存索引库的IndexWriter
indexWriter = new IndexWriter(ram,Configuration.analyzer,MaxFieldLength.LIMITED);
//添加新的数据
Article article = new Article(45,"panpan","love you");
indexWriter.addDocument(DocumentUtils.docConvert(article, Document.class));
/**一个索引库只能有一个IndexWriter,一一对应.
* 同时,同一时刻只能有一个IndexWriter,如果有两个,不能写同一个文件,不然就有问题
*/
indexWriter.close();
/**这个IndexWriter是针对文件系统的
* 第三个参数是指: 如果指定为true,表示重新创建索引库,如果已存在,就删除后再创建;
* 指定为false,表示追加(默认值)
* 如果不存在,就抛异常.
*/
indexWriter = new IndexWriter(Configuration.directory,Configuration.analyzer,true,MaxFieldLength.LIMITED);
/**
* 将指定目录添加到文件系统中,并且不优化
* 如果传入一个IndexReader,可以进行优化:
IndexReader indexReader = IndexReader.open(ram);
indexWriter.addIndexes(indexReader);
*/
indexWriter.addIndexesNoOptimize(ram);
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
ram.close();
indexWriter.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
--------------------------------------------------------------------------------
Analyzer(分词器)
分词器能以某种规则对关键字进行分词,将分好的词放到目录中,以作为检索到的条件,在创建索引时会使用到分词器,在搜索时也将用到分词器,这两个地方要使用同一个分词器,否则可能找不到结果.分词器一般的工作流程:
1.切分关键词
2.去除停用词
3.对于英文单词,把所有字母转为小写
注:有的分词器对英文支持的非常好,还能对英文单词进行时态还原.
停用词的概念
有些词在文本中出现的频率非常高,但是对文本所携带的信息基本不产生影响,例如英文的“a、an、the、of”,或中文的“的、了、着”,以及各种标点符号等,这样的词称为停用词(stop word).文本经过分词之后,停用词通常被过滤掉,不会被进行索引.在检索的时候,用户的查询中如果含有停用词,检索系统也会将其过滤掉(因为用户输入的查询字符串也要进行分词处理).排除停用词可以加快建立索引的速度,减小索引库文件的大小
常用的中文分词器
中文的分词比较复杂,因为不是一个字就是一个词,而且一个词在另外一个地方就可能不是一个词,如在"帽子和服装"中,"和服"就不是一个词.对于中文分词,通常有三种方式:
•单字分词
•二分法分词
•词典分词
单字分词:就是按照中文一个字一个字地进行分词.如:"我们是中国人",效果:"我"、"们"、"是"、"中"、"国"、"人".(StandardAnalyzer就是这样)
二分法分词:按两个字进行切分.如:"我们是中国人",效果:"我们"、"们是"、"是中"、"中国"、"国人".(CJKAnalyzer就是这样)
词库分词:按某种算法构造词,然后去匹配已建好的词库集合,如果匹配到就切分出来成为词语.通常词库分词被认为是最理想的中文分词算法.如:"我们是中国人",效果为:"我们"、"中国人".(使用极易分词的MMAnalyzer.可以使用极易分词,或者是庖丁分词分词器、IKAnalyzer等).
测试分词器
/**
* 使用指定的分词器对指定的文本进行分词,并打印结果
* @param analyzer
* @param text
* @throws Exception
*/
private void testAnalyzer(Analyzer analyzer, String text) throws Exception {
System.out.println("当前使用的分词器:" + analyzer.getClass());
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
tokenStream.addAttribute(TermAttribute.class);
while (tokenStream.incrementToken()) {
TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class);
System.out.println(termAttribute.term());
}
}
Highlighter(高亮器)
在搜索结果中经常可以看到,自己搜索的关键字加上了一些效果,以突出显示,Lucene自然提供了这样的设置,我们需要用到Highlighter这个类,用之前需要配置好:
/**
* Formatter:设置高亮器的格式,无参构造函数表示使用<b>标签
* Scorer:Highlighter需要知道哪些关键词是需要高亮的,需要需要查询条件
*/
Formatter formatter = new SimpleHTMLFormatter();
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(formatter,scorer);
//除了上面两个以外,还需要生成一段摘要,以便搜索的时候显示,指定摘要的大小为20个字符
Fragmenter fragmenter = new SimpleFragmenter(20);
highlighter.setTextFragmenter(fragmenter);
只需要配置这三样就可以了,接着我们要在每一次获取Field对象数据的时候做一些工作,因为高亮器实际上就是在内容中加了一点样式,我们当然要指定在哪里加:
/**
* 在循环获取每一条记录的时候,让高亮器找到需要高亮的关键词,
* 要提供相应的分词器和告诉它高亮哪一个Field中的内容
* 一次只能高亮一个Field,如需要高亮多个Field,需要写多次
* 就像这样:
String text1 = highlighter.getBestFragment(
Configuration.analyzer, "title",
doc.get("title"));
*/
String text = highlighter.getBestFragment(Configuration.analyzer, "content", doc.get("content"));
if(text != null){
doc.getField("content").setValue(text);
}
一定要放在循环里面,highlighter.getBestFragment()方法本身没有副作用,也就是不改变原有的值,返回一个改变后的结果,所以要手动地改变Field中原有的值,并且if的条件最好不要省略,有时候可以会有这样一种情况,出现关键字的位置在其他Field里面,所以如果当前高亮的属性值中没有出现搜索关键字,则返回null.
排序
排序有几种方式,最常用的也就是相关度排序,把最有可能是用户需要的数据放在前面.由高到低排序,默认即是使用相关度排序.当然,我们也可以控制相关度排分的比重,比如我们想让一条记录的得分加倍,就要在建立索引时,加几句操作:
Document doc = DocumentUtils.docConvert(article, Document.class);
//setBoost()方法需要一个float类型的参数,表示将相关度得分的因子增加多少倍
doc.setBoost(2F);
indexWriter.addDocument(doc);
这样加进去的索引,就会改变默认的相关度得分因子.如果我们想靠某个Field的值来排序也可以,默认是升序,如果是按某个Field的值来排序,那将不会生成相关度得分,因为没有必要.假设按ID进行升序排列:
Sort sort = new Sort(new SortField("id",SortField.INT));
TopDocs topDocs = indexSearcher.search(query,null, 100,sort);
IndexSearcher的search()方法需要改成接收4个参数的重载方法,第二个参数需要一个Filter,这里不需要,就传入null,Sort需要知道按什么排序,由SortField的第一个构造参数指明,第二参数指明类型,接收一个int值,由SortField对象的常量值表示.还可以加入第三个参数:
Sort sort = new Sort(new SortField("id", SortField.INT, true));
表示是否倒序排序.也可以指定多个排序规则.由多个SortField组成第1顺序、第2顺序...
过滤
使用Filter可以对搜索结果进行过滤,以获得更小范围的结果.使用Filter对性能的影响很大(有可能会使查询慢上百倍).假如我要看ID从5到15的:
//第三个参数:是否包含最小值(5);第四个参数:是否包含最大值(15)
Filter filter = NumericRangeFilter.newIntRange("id", 5, 15, true,true);
//这个时候就不需要第四个参数来指定排序了,search()这个方法有很多重载版本
TopDocs topDocs = indexSearcher.search(query,filter, 100);
光这样写还不行,会看不到结果.这是因为要过滤的值,如果是数字,需要以指定的格式存储才行,否则将按字符串的方式来比较.
对于这个问题,需要引出一个工具类:NumericUtils,这个工具类专门做数值与数值或字符串间的转换工作.要在对象到Document以及Document到对象的转换的时候进行,这是对于数值,如果是日期类型,需要使用这个工具类:DateTools.
注:这样做了以后,可能还是不行,对于使用NumericUtils把数字转换为字符串,一定要使用Index.NOT_ANALYZED,以保存能够正确的使用Filter
其他搜索
首先,有两种搜索方式:
1.使用QueryParser(或MultiFieldQueryParser)解析查询字符串的方式
2.自己直接创建Query子类的实例方式
由于可以使用Query对象的toString()方法打印出对应的查询语法,所以以第二种方式做的话,可以看相应的第一种查询方法:
/* 1.匹配所有对应的查询字符串为: *:*
Query query = new MatchAllDocsQuery();
2.范围查询对应的查询字符串为: id:[5 TO 15]
Query query = NumericRangeQuery.newIntRange("id", 5, 15, true, true);
范围查询对应的查询字符串为: id:{5 TO 15}
Query query = NumericRangeQuery.newIntRange("id", 5, 15, false,false);
范围查询对应的查询字符串为: id:{5 TO 15]
Query query = NumericRangeQuery.newIntRange("id", 5, 15, false, true);
3.关键词对应的查询字符串为: title:lucene
Query query = new TermQuery(new Term("title", "lucene"));
4.通配符对应的查询字符串为: title:lucen?
Query query = new WildcardQuery(new Term("title", "lucen?"));
通配符对应的查询字符串为: title:lu*ne
Query query = new WildcardQuery(new Term("title", "lu*ne"));
5.短语对应的查询字符串为: title:"lucene ? ? 工作"
PhraseQuery phraseQuery = new PhraseQuery();
phraseQuery.add(new Term("title", "lucene"), 0); // 第一个词的索引是0
phraseQuery.add(new Term("title", "工作"), 3);
短语对应的查询字符串为: title:"lucene 工作"~5
phraseQuery.add(new Term("title", "lucene"));
phraseQuery.add(new Term("title", "工作"));
phraseQuery.setSlop(5); // 指定这些词中间的间隔最多不会超过5个词
6.布尔查询
对应的查询语法两种:
1. + 代表MUST,-表示NOT
2. AND、OR、NOT,注意要全是大写
3. MUST 必须满足
MUST_NOT 非
SHOULD 多个SHOULD一起用,是OR的关系
Query query1 = new TermQuery(new Term("title", "lucene"));
Query query2 = NumericRangeQuery.newIntRange("id", 5, 15, false, true);
对应的查询字符串为: +title:lucene +id:{5 TO 15]
对应的查询字符串为: title:lucene AND id:{5 TO 15]
booleanQuery.add(query1, Occur.MUST);
booleanQuery.add(query2, Occur.MUST);
对应的查询字符串为: +title:lucene -id:{5 TO 15]
对应的查询字符串为: title:lucene NOT id:{5 TO 15]
booleanQuery.add(query1, Occur.MUST);
booleanQuery.add(query2, Occur.MUST_NOT);
对应的查询字符串为: title:lucene id:{5 TO 15]
对应的查询字符串为: title:lucene OR id:{5 TO 15]
booleanQuery.add(query1, Occur.SHOULD);
booleanQuery.add(query2, Occur.SHOULD);
----------------------------------------------------
MUST + SHOULD,与只有一个MUST效果相同
SHOULD + MUST_NOT,这时SHOULD就相当MUST
MUST_NOT + MUST_NOT,没有匹配结果,也不报错。
*/
--------------------------------------------------------------------------------
如本文用词不严谨,或者不恰当等任何问题,请不啬赐教.
本文来自CSDN博客,转载请标明出处:http://www.uspcat.com/myknowledgebase/lucene/Lucene3_xuexibiji.mht
发表评论
-
Solr4.0+IKAnalyzer中文分词安装
2012-11-29 19:14 1592有近2年没接触Solr跟Lucene ... -
solr搜索打分规制排序
2012-09-26 21:58 2411solr使用了Lucene的内核,也继承了Luce ... -
solr DataimportHanler
2012-09-22 17:01 1258大多数的应用程序将数据存储在关系数据库、xml文件 ... -
solr第一弹 autocomplete(自动补全)
2012-09-22 16:38 1470百度和google中都有 ... -
全文搜索服务器solr之客户端 - solrj二次开发
2012-09-21 09:07 4874Solrj已经是很强大的solr客户端了。它本身就包装了h ... -
Solr Data Import 快速入门
2012-09-20 14:32 840原文出处:http://blog.chenl ... -
JAVA环境下利用solrj二次开发SOlR搜索的环境部署常见错误
2012-09-20 11:36 1797问题一:出现控制台坏的响应错误一Bad reque ... -
Solr学习总结
2012-09-20 10:06 6445一、 SOLR搭建企业搜索平台 运行环境: 运行容器:Tomc ... -
olr 的客户端调用solrj 建索引+分页查询
2012-09-20 08:54 1940在 solr 3.5 配置及应用(一) 讲过一了 sol ... -
Solr笔记
2012-09-19 23:07 1295... -
Apache Solr 初级教程(介绍、安装部署、Java接口、中文分词)
2012-09-19 22:56 1776Apache Solr 介绍 Solr 是 ... -
lucene3.0 分页显示与高亮显示(转)
2012-09-19 11:44 1739分页类 Java代码 pac ... -
lucene3 中文IKAnalyzer分词例子
2012-09-10 13:37 1188import java.io.IOException; im ... -
Compass2.0.2自带例子解析
2012-09-05 08:47 1472Compass2.0.2自带例子解析: 下面的代码来自com ... -
compass站内搜索
2012-09-05 08:49 1006compass站内搜索: 1.去官方网站下载compass的 ... -
Spring + Compass + paoding配置
2012-09-05 08:50 1059Spring + Compass + paoding配置: ... -
配置compass的索引位置为相对路径
2012-09-01 10:49 1375配置compass的索引位置为相对路径: Compass是对 ... -
lucene创建索引
2012-09-01 10:48 1096lucene创建索引: import java.io.Fi ... -
Lucene demo调试运行:
2012-09-01 10:47 2033Lucene demo调试运行: 运行环境: JDK ... -
SSH + Lucene + 分页 + 排序 + 高亮 模拟简单新闻网站搜索引擎
2012-09-01 10:43 3465前两天看到了一个中国新闻网,这个网站的搜索form的a ...
相关推荐
《深入理解Lucene 3.0.1:库与源代码解析》 ...通过源代码学习,开发者不仅可以掌握Lucene的工作原理,还能根据需求进行定制化开发。无论是构建搜索引擎还是提升现有系统的搜索功能,Lucene都是一个值得信赖的选择。
**Lucene 3.0.1 全文检索引擎** Lucene 是 Apache 软件基金会的一个开源项目,它是一个高性能、全文本搜索库,提供了一个简单但功能强大的API,用于在各种应用中实现全文检索功能。Lucene 3.0.1 版本是该库的一个...
《深入剖析Lucene 3.0.1:Java开源搜索引擎框架》 Lucene是一个由Apache软件基金会开发的全文检索库,它为构建高效、可扩展的搜索应用提供了强大的支持。在Java开发领域,Lucene以其优秀的性能和易用性赢得了广泛的...
Lucene 3.0.1是该库的一个重要版本,它在前一版本的基础上进行了一些改进和优化,为开发者提供了更稳定和高效的搜索解决方案。 在Lucene 3.0.1中,官方API(应用程序编程接口)是开发者理解和使用Lucene的核心工具...
lucene-core-3.0.1.jar(核心包) contrib\analyzers\common\lucene-analyzers-3.0.1.jar(分词器) contrib\highlighter\lucene-highlighter-3.0.1.jar(高亮) contrib\memory\lucene-memory-3.0.1.jar(高亮)
全文检索工具包Lucene 3.0.1版本
**Lucene 3.0.1全文检索引擎的架构** Lucene是一款开源的全文检索库,由Apache软件基金会开发,广泛应用于各种搜索引擎的构建。在3.0.1版本中,Lucene提供了一套高效、可扩展的文本搜索解决方案。其核心特性包括...
【Lucene 3.6 学习笔记】 Lucene 是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发。本文将深入探讨Lucene 3.6版本中的关键概念、功能以及实现方法。 ### 第一章 Lucene 基础 #### 1.1 索引部分的核心...
Lucene 3.0.1 是该项目的一个历史版本,尽管较新版本可能包含更多的改进和特性,但这个版本仍然具有重要的学习价值,特别是对于想了解 Lucene 历史和演进的人来说。 在 `lucene-3.0.1` 压缩包中,我们可以找到以下...
### Lucene 3.5 学习笔记 #### 一、Lucene 3.5 基本概念 ##### 1.1 Lucene 概述 **1.1.1 IndexWriter** `IndexWriter` 是 Lucene 中的核心类之一,用于创建或更新索引。它提供了添加文档、删除文档、优化索引等...
lucene使用总结笔记lucene使用总结笔记lucene使用总结笔记lucene使用总结笔记lucene使用总结笔记
《Lucene 3.0 学习笔记(三)与Paoding整合》 在深入了解Lucene 3.0的过程中,我们经常会遇到如何将其与第三方工具进行整合的问题,以提升搜索性能和用户体验。这篇学习笔记主要关注的是将Lucene 3.0与Paoding搜索...
《Lucene 3.5 学习笔记》 在信息技术高速发展的今天,搜索引擎技术成为了信息检索的核心工具。Apache Lucene,作为一个开源全文检索库,为开发者提供了强大的文本搜索功能。本文将深入探讨Lucene 3.5版本的相关知识...
Lucene-3.0.1API,包含用例。
**Lucene 基础学习笔记与源码分析** **一、Lucene 概述** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发并维护。它是一个 Java 开发的开源项目,被广泛应用于各种搜索引擎的构建,支持多种编程...
《深入理解Lucene 2.9.1:构建与搜索的全方位解析》 Lucene,作为一款开源的全文搜索引擎库,被广泛应用于各种信息检索场景。本文将详细讲解Lucene 2.9.1版本的核心概念、架构以及索引创建与搜索的流程。 一、...
lucene-analyzers-3.0.1.jar,lucene-analyzers-3.0.1.jar
《全面解析:Lucene-3.0.1 API——基于最新整理资料》 在信息技术日新月异的今天,搜索引擎技术扮演着至关重要的角色。Apache Lucene,作为一款开源的全文检索库,为开发者提供了强大的文本搜索功能。本文将基于...