- 浏览: 801071 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
107x:
不错,谢谢!
log4j.properties配置详解 -
gzklyzf:
为啥我解析的PDF文档没有作者、文章题目等信息啊,下面是我的代 ...
Apache Lucene Tika 文件内容提取工具 -
mervyn1024:
解压密码是啥
ictclas4j调整 -
百卉含英:
如果我的文件输出路径是这个log4j.appender.Fil ...
log4j.properties配置详解 -
lxhxklyy:
mark……
log4j.properties配置详解
Lucene搜索方法总结
更多lucene信息欢迎查看http://summerbell.iteye.com/category/91859
1.多字段搜索
使用 multifieldqueryparser 可以指定多个搜索字段。
query query = multifieldqueryparser.parse(”name*”, new string[] { fieldname, fieldvalue }, analyzer);
indexreader reader = indexreader.open(directory);
indexsearcher searcher = new indexsearcher(reader);
hits hits = searcher.search(query);
2.多条件搜索
除了使用 queryparser.parse 分解复杂的搜索语法外,还可以通过组合多个 query 来达到目的。
query query1 = new termquery(new term(fieldvalue, “name1′)); // 词语搜索
query query2 = new wildcardquery(new term(fieldname, “name*”)); // 通配符
//query query3 = new prefixquery(new term(fieldname, “name1′)); // 字段搜索 field:keyword,自动在结尾添加 *
//query query4 = new rangequery(new term(fieldnumber, numbertools.longtostring(11l)), new term(fieldnumber, numbertools.longtostring(13l)), true); // 范围搜索
//query query5 = new filteredquery(query, filter); // 带过滤条件的搜索
booleanquery query = new booleanquery();
query.add(query1, booleanclause.occur.must);
query.add(query2, booleanclause.occur.must);
indexsearcher searcher = new indexsearcher(reader);
hits hits = searcher.search(query);
3.过滤
使用 filter 对搜索结果进行过滤,可以获得更小范围内更精确的结果。
举个例子,我们搜索上架时间在 2005-10-1 到 2005-10-30 之间的商品。
对于日期时间,我们需要转换一下才能添加到索引库,同时还必须是索引字段。 // index
document.add(fielddate, datefield.datetostring(date), field.store.yes, field.index.un_tokenized);
//…
// search
filter filter = new datefilter(fielddate, datetime.parse(”2005-10-1′), datetime.parse(”2005-10-30′));
hits hits = searcher.search(query, filter);
除了日期时间,还可以使用整数。比如搜索价格在 100 ~ 200 之间的商品。
lucene.net numbertools 对于数字进行了补位处理,如果需要使用浮点数可以自己参考源码进行。 // index
document.add(new field(fieldnumber, numbertools.longtostring((long)price), field.store.yes, field.index.un_tokenized));
//…
// search
filter filter = new rangefilter(fieldnumber, numbertools.longtostring(100l), numbertools.longtostring(200l), true, true);
hits hits = searcher.search(query, filter);
使用 query 作为过滤条件。 queryfilter filter = new queryfilter(queryparser.parse(”name2′, fieldvalue, analyzer));
我们还可以使用 filteredquery 进行多条件过滤。
filter filter = new datefilter(fielddate, datetime.parse(”2005-10-10′), datetime.parse(”2005-10-15′));
filter filter2 = new rangefilter(fieldnumber, numbertools.longtostring(11l), numbertools.longtostring(13l), true, true);
query query = queryparser.parse(”name*”, fieldname, analyzer);
query = new filteredquery(query, filter);
query = new filteredquery(query, filter2);
indexsearcher searcher = new indexsearcher(reader);
hits hits = searcher.search(query);
4.分布搜索
我们可以使用 multireader 或 multisearcher 搜索多个索引库。
multireader reader = new multireader(new indexreader[] { indexreader.open(@”c:\index”), indexreader.open(@”\\server\index”) });
indexsearcher searcher = new indexsearcher(reader);
hits hits = searcher.search(query);
或
indexsearcher searcher1 = new indexsearcher(reader1);
indexsearcher searcher2 = new indexsearcher(reader2);
multisearcher searcher = new multisearcher(new searchable[] { searcher1, searcher2 });
hits hits = searcher.search(query);
还可以使用 parallelmultisearcher 进行多线程并行搜索。
5.显示搜索语法字符串
我们组合了很多种搜索条件,或许想看看与其对等的搜索语法串是什么样的。 booleanquery query = new booleanquery();
query.add(query1, true, false);
query.add(query2, true, false);
//…
console.writeline(”syntax: {0}”, query.tostring());
输出:
syntax: +(name:name* value:name*) +number:[0000000000000000b to 0000000000000000d]
呵呵,就这么简单。
6.如何删除索引
lucene提供了两种从索引中删除document的方法,一种是
void deleteDocument(int docNum)
这种方法是根据document在索引中的编号来删除,每个document加进索引后都会有个唯一编号,所以根据编号删除是一种精确删除,但是这个编号是索引的内部结构,一般我们不会知道某个文件的编号到底是几,所以用处不大。另一种是
void deleteDocuments(Term term)
这种方法实际上是首先根据参数term执行一个搜索操作,然后把搜索到的结果批量删除了。我们可以通过这个方法提供一个严格的查询条件,达到删除指定document的目的。
下面给出一个例子:
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexReader reader = IndexReader.open(dir);
Term term = new Term(field, key);
reader.deleteDocuments(term);
reader.close();
ms还有操作
deleteDocuments(Term);
deleteDocuments(Term[]);
deleteDocuments(Query);
deleteDocuments(Query[]);
7.如何更新索引
注:据多人反应,新版本的lucene以及提供了更新索引的方法。
writer.updateDocument(doc);
————————————————————javaeye分割线——————————————
lucene并没有提供专门的索引更新方法,我们需要先将相应的document删除,然后再将新的document加入索引。例如:
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexReader reader = IndexReader.open(dir);
Term term = new Term(“title”, “lucene introduction”);
reader.deleteDocuments(term);
reader.close();
IndexWriter writer = new IndexWriter(dir, 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 is funny", Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(doc);
writer.optimize();
writer.close();
8.多样化的搜索
/** *** 一个关键字,对一个字段进行查询 **** */
QueryParser qp = new QueryParser("content",analyzer);
query = qp.parse(keyword);
Hits hits = searcher.search(query);
/** *** 模糊查询 **** */
Term term = new Term("content",keyword);
FuzzyQuery fq = new FuzzyQuery(term);
Hits hits = searcher.search(fq);
/** *** 一个关键字,在两个字段中查询 **** */
/*
* 1.BooleanClause.Occur[]的三种类型: MUST : + and MUST_NOT : - not SHOULD : or
* 2.下面查询的意思是:content中必须包含该关键字,而title有没有都无所谓
* 3.下面的这个查询中,Occur[]的长度必须和Fields[]的长度一致。每个限制条件对应一个字段
*/
BooleanClause.Occur[] flags = new BooleanClause.Occur[]{BooleanClause.Occur.SHOULD,BooleanClause.Occur.MUST};
query=MultiFieldQueryParser.parse(keyword,new String[]{"title","content"},flags,analyzer);
/** *** 两个(多个)关键字对两个(多个)字段进行查询,默认匹配规则 **** */
/*
* 1.关键字的个数必须和字段的个数相等
* 2.由于没有指定匹配规定,默认为"SHOULD" 因此,下面查询的意思是:"title"中含有keyword1 或 "content"含有keyword2.
* 在此例中,把keyword1和keyword2相同
*/
query=MultiFieldQueryParser.parse(new String[]{keyword,keyword},new
String[]{"title","content"},analyzer);
/** *** 两个(多个)关键字对两个(多个)字段进行查询,手工指定匹配规则 **** */
/*
* 1.必须 关键字的个数 == 字段名的个数 == 匹配规则的个数
* 2.下面查询的意思是:"title"必须不含有keyword1,并且"content"中必须含有keyword2
*/
BooleanClause.Occur[] flags = new
BooleanClause.Occur[]{BooleanClause.Occur.MUST_NOT,BooleanClause.Occur.MUST};
query=MultiFieldQueryParser.parse(new String[]{keyword,keyword},new
String[]{"title","content"},flags,analyzer);
/** *** 对日期型字段进行查询 **** */
/** *** 对数字范围进行查询 **** */
/*
* 1.两个条件必须是同一个字段
* 2.前面一个条件必须比后面一个条件小,否则找不到数据
* 3.new RangeQuery中的第三个参数,表示是否包含"=" true: >= 或 <= false: > 或 <
* 4.找出 55>=id>=53 or 60>=id>=57:
*/
Term lowerTerm1 = new Term("id","53");
Term upperTerm1 = new Term("id","55");
RangeQuery rq1 = new RangeQuery(lowerTerm1,upperTerm1,true);
Term lowerTerm2 = new Term("id","57");
Term upperTerm2 = new Term("id","60");
RangeQuery rq2 = new RangeQuery(lowerTerm2,upperTerm2,true);
BooleanQuery bq = new BooleanQuery();
bq.add(rq1,BooleanClause.Occur.SHOULD);
bq.add(rq2,BooleanClause.Occur.SHOULD);
Hits hits = searcher.search(bq);
9.结果排序
排序的关键点有两个:
1:首先你要排序的字段必须是被index的,并且是untokenized的。
如:
doc.add(new Field("click", dv.get("click").toString(), Field.Store.NO, Field.Index.UN_TOKENIZED));
2:在检索时候:
如:
/***** 排序 *****/
/*
* 1.被排序的字段必须被索引过(Indexecd),在索引时不能 用 Field.Index.TOKENIZED
* (用UN_TOKENIZED可以正常实现.用NO时查询正常,但排序不能正常设置升降序)
* 2.SortField类型
* SCORE、DOC、AUTO、STRING、INT、FLOAT、CUSTOM 此类型主要是根据字段的类型选择
* 3.SortField的第三个参数代表是否是降序true:降序 false:升序
*/
Sort sort = new Sort(new SortField[]{new SortField("click", SortField.INT, true)});
Hits hits = searcher.search(querystring,sort);
/*
* 按日期排序
*/
Sort sort = new Sort(new SortField[]{new SortField("createTime", SortField.INT, false)});
/***** 过滤器 ******/
QueryParser qp1 = new QueryParser("content",analyzer);
Query fquery = qp1.parse("我");
BooleanQuery bqf = new BooleanQuery();
bqf.add(fquery,BooleanClause.Occur.SHOULD);
QueryFilter qf = new QueryFilter(bqf);
Hits hits = searcher.search(query);
10.将小索引文件合并到大的索引文件中去(此方法性能不佳)
/** 将小索引文件合并到大的索引文件中去
* @param from 将要合并到to文件的文件
* @param to 将from文件合并到该文件
* @param analyzer
*/
private void mergeIndex(File from,File to,Analyzer analyzer)
{
IndexWriter indexWriter = null;
try{
System.out.println("正在合并索引文件!\t");
indexWriter = new IndexWriter(to,analyzer, false);
indexWriter.setMergeFactor(100000);
indexWriter.setMaxFieldLength(Integer.MAX_VALUE);
indexWriter.setMaxBufferedDocs(Integer.MAX_VALUE);
indexWriter.setMaxMergeDocs(Integer.MAX_VALUE);
FSDirectory[] fs = {FSDirectory.getDirectory(from,false)};
indexWriter.addIndexes(fs);
indexWriter.optimize();
indexWriter.close();
System.out.println("已完成合并!\t");
}
catch(Exception e)
{
Utility.writeLog("合并索引文件出错!mergeIndex()"+e.getMessage(),"");
}
finally
{
try{
if(indexWriter!=null)
indexWriter.close();
}
catch(Exception e ){
}
}
}
合并时间是从每天的凌晨3点钟开始,一直到早上9点左右,足足用5个小时才合并完成,其中大索引文件大小为4G,小索引为10MB.
11.问题2:单字共现频率的局部统计的原理
解答:
高频字串统计的理论基础是N - 元模型。
设W1 W2 ...WN 是长度为N 的字串,则字串W 的似然度为
p ( W) = p ( w i | w1 w2 ...w i - 1) (1)
上面公式的意义反映连续个N 字之间的结合程度,如果若干种不同的历史组合W1 W2 ...WN的最后N - 1 个字相同,就把它们都看作一类。在这一假设下,每一个字出现的概率不再与前面的历史有关,只与最近的N - 1 个字相关,字串的先验概率为
p ( W) = p ( w i - ( n - 1) w i - ( n - 2) ...w i - 1) (2)
当p ( W) 超过一定的阈值时,说明这N 个字的结合能力较强,我们就可以认为该字串能被看成一个“词”。
正是根据以上所说原理,预先对待分词文本每个单字进行出现次数统计并记录它们在文中出现的位置(存储方式如附件图例所示),预处理后我们遍历单字频次统计 列表出现次数大于2的所有单字在文中出现的位置i,判断位置i+1的单字出现次数是否也大于2,若是则判断位置i+2的单字出现次数是否也大于2,如此类 推直至位置i+n+1的单字出现次数小于2,获得候选词组 w(i,i+1...i+n)并放入候选词汇集合,最后对候选词汇集合进行前缀后缀处理获得合适的高频词汇集合result
writer.addIndexes(indexDirs); 12.索引合并
评论
附件?我只知道将附件视为一个文本来做,同时与正文关联~
你给的链接是不是你编辑文章时候的那个链接?而不是发布之后的?(猜测...)
lz 能不能讲解下 RemoteSearchable 这个相关使用?
对lz的分布式搜索比较感兴趣~~
谢谢~
链接问题是我自己大意了~已修正。
至于RemoteSearchable,lucene java项目自己是没有提供的。
据说可以采用分布式文件系统,如Hadoop中的HDFS。
另一个很直观的做法就是自己写一个分布式通信系统,轮询多台存放lucene索引的节点,并整合每个节点返回的结果作为最后的搜索结果。
我自己使用的是最偷懒的做法,放弃了lucene java,而转用mysql的全文检索功能。这样每个mysql数据库维护一套索引,用的时候直接查就好,通信系统mysql自带了。我觉得mysql比lucene唯一有缺陷的地方在于mysql没有一个很好的评级公式,来计算文档与查询的相关度。不过我们可以自己实现该评级公式,仿造lucene或者原创一个。效果也挺好的。
主要因为我在实验室里,对性能什么要求不高,少写代码多办事是王道。
细节就比较麻烦了,大概思路是这样,多多交流了。
hdfs曾经考虑过..由于种种原因而搁置.
现在研究lucene自带的各种remoteSearch..
跟lz情况恰好相反...我在实验室做导师的工程项目..要求性能、并发,事就那么多..怎么快怎么来..
多多交流~~
你给的链接是不是你编辑文章时候的那个链接?而不是发布之后的?(猜测...)
lz 能不能讲解下 RemoteSearchable 这个相关使用?
对lz的分布式搜索比较感兴趣~~
谢谢~
链接问题是我自己大意了~已修正。
至于RemoteSearchable,lucene java项目自己是没有提供的。
据说可以采用分布式文件系统,如Hadoop中的HDFS。
另一个很直观的做法就是自己写一个分布式通信系统,轮询多台存放lucene索引的节点,并整合每个节点返回的结果作为最后的搜索结果。
我自己使用的是最偷懒的做法,放弃了lucene java,而转用mysql的全文检索功能。这样每个mysql数据库维护一套索引,用的时候直接查就好,通信系统mysql自带了。我觉得mysql比lucene唯一有缺陷的地方在于mysql没有一个很好的评级公式,来计算文档与查询的相关度。不过我们可以自己实现该评级公式,仿造lucene或者原创一个。效果也挺好的。
主要因为我在实验室里,对性能什么要求不高,少写代码多办事是王道。
细节就比较麻烦了,大概思路是这样,多多交流了。
你给的链接是不是你编辑文章时候的那个链接?而不是发布之后的?(猜测...)
lz 能不能讲解下 RemoteSearchable 这个相关使用?
对lz的分布式搜索比较感兴趣~~
谢谢~
这个……好像javaeye规定要登录才可以看……不是我个人设置的……
确实,已经有朋友提到了,我现在加进来。
3.0中的实现机制貌似还是先删再添加~
没错。准确的说3.0的update是
writer.updateDocument(term, doc);
这里的term是删除索引用的,doc是建立新索引用的。有着2个参数自己都能实现update。
确实,已经有朋友提到了,我现在加进来。
更新索引,也许以前的版本是没有的
多谢,收藏进来。
PDF,要先转化为TXT才行。你可以看看PDFBOX。
更新索引,也许以前的版本是没有的
lz对compass完全陌生,只知道compass也是在lucene基础上提供的全文检索服务。那么其搜索方式大约有一定的共性。
lz的主要研究领域在信息检索上(http://summerbell.iteye.com/category/91863),如果在这方面有问题欢迎交流~
您没有权限执行这项操作,请检查登录的账号是否正确
楼主能讲讲不同文件格式文档的(比如pdf,xml)解析和建索引吗
至于pdf,xml等的解析和建索引,我先说解析。
常用的文件格式如pdf,doc(x),ppt(x),html,甚至包括Java class,image都可以通过内容抽取的工具Tika来完成。
话说其实一般说的lucene是指lucene java,是Apache Lucene下的一个子项目。其他子项目包括大名鼎鼎的Nutch以及我在这里提到的Tika。
Tika的更多信息和示例代码你可以查看http://summerbell.iteye.com/blog/565922,
我给出了Tika抽取docx,pdf,和html文件的代码和需要的jar包。
另外:
附件的问题我也觉得很诡异。
回头排查一下,似乎传上去以后改变了……
发表评论
-
Stanford Dependence Relations(zz)
2014-09-08 10:50 1071中心语为谓词 subj -- 主语 nsubj -- 名 ... -
发现庖丁分词器的一个小问题
2014-09-06 11:02 565”深圳市集银科技有限公司“ 会被切分成: ... -
ictclas4j调整
2012-01-17 17:12 2210Ictclas4j在处理一些文档片段时候,会报如下异常: ... -
Ictclas的一个bug(转)
2011-12-15 17:44 1616SegTag tag=new SegTag(4); S ... -
Ubuntu下ICTCLAS JNI的使用
2011-11-14 17:46 4229首先下载ICTCLAS2011_Linux_32_jni ,解 ... -
OneMain
2011-10-24 17:09 1292import org.ictclas4j.bean.SegRe ... -
资料准备
2010-03-09 16:16 1072筹备 RegExr(正则表达式)(舍去) Tika ... -
如何对一个Document的不同Filed使用不同的分词器
2010-02-25 15:13 1346如何对一个Document的不同Filed使用不同的分词器 ... -
Luke简介
2010-01-11 19:49 2141Luke简介 Luke是一个方便的开发和诊断工具,它能访问L ... -
Apache Lucene Tika 文件内容提取工具
2010-01-08 15:56 17210Tika入门 Tika是一个内容抽取的工具集合(a t ... -
What Is Lucene?
2010-01-05 22:43 1305What Is Lucene? The Apache ... -
ictclas4j词性表
2009-11-15 22:14 20761. 名词 (1个一类,7个二类,5个三类) 名词分为以下 ... -
Lucene Hack之通过缩小搜索结果集来提升性能
2009-08-23 20:19 1169一、缘起 Lucene在索引文件上G之后的搜索性能下降很严 ... -
Lucene基础排序算法改进
2009-08-23 17:47 2874Lucene基础排序算法: score_d = sum_t( ... -
ictclas4j分词模块
2009-05-19 14:39 3197ictclas4j中文分词模块ms也是采用了 ... -
关于imdict-chinese-analyzer中文分词模块
2009-05-19 12:00 3148CJK中文分词模块是很重要的工具。imdic ...
相关推荐
Lucene2.4入门总结lucene2.4 人门 field 多条件搜索
Lucene搜索过程的核心类 IndexSearcher:用于搜索IndexWriter创建的索引 Term:用于搜索的一个基本单元包括了一对字符串元素,与Field相对应 Query :抽象的查询类 TermQuery:最基本的查询类型,用来匹配特定Field...
Lucene搜索引擎开发权威经典 光盘 于天恩 著 中国铁道出版社出版 2008-10 这本书基于Lucene的当前最新版本(2.1)精解了Lucene搜索引擎的相关知识,从基础知识到应用开发,精练简洁,恰到好处。 本书共包括16章,...
一步一步跟我学习lucene是对近期做lucene索引的总结,
[硕士论文]_基于Lucene的Web搜索引擎实现.pdf [硕士论文]_基于MapReduce的分布式智能搜索引擎框架研究.pdf [硕士论文]_基于Nutch的垂直搜索引擎的分析与实现.pdf 一个例子学懂搜索引擎(lucene).doc 中文搜索引擎技术...
探讨了Lucene和Heritrix在构建垂直搜索引擎中的应用。 1、垂直搜索引擎的基本介绍 2、基于Java 的全文检索引擎—Jakarta Lucene 3、网络爬虫Heritrix 4、Lucene和Heritrix在构建垂直搜索引擎中的应用(含代码) 5、...
结合笔者的实际开发经验,总结了一些新的开发技巧和开发思路,并对网上流传的一些错误技术点和代码进行验证,同时给出正确的思路,旨在给开发者提供一本清晰、完整、易懂的指导手册。本书既可为零起点的Lucene初学者...
前段时间学习lucene的总结,因为版本已经更新到了3.2,一些API有更新,很多现有的网页上找到的教程都跑不了。
2:各种搜索方式方法 3:删除索引 4:检查索引文件 5:恢复删除的索引 6:强制删除 7:更新索引 8:合并索引 9:高亮回显 供大家参考学习 public static void main(String[] args) { LuceneUtil luceneUtil = new ...
1.12 Lucene学习总结之七:Lucene搜索过程解析(1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .206 1.13 Lucene学习总结之七:Lucene搜索过程解析(2) . . . . . . . . . . . . ....
此博文是对近期做lucene索引的总结, (lucene,solr,netty,hadoop),如蒙加入,不胜感激,大家共同探讨,本人争取每日一博,希望大家关注呦
NULL 博文链接:https://zzc1684.iteye.com/blog/2181330
lucene是一个全文搜索框架,它提供接口,由用户自由实现。 本资源为对lucene的学习+收集
用简单的例子介绍了Lucene的最新应用方法,包括完整的搜索实现过程:从完成索引到搜索用户界面的实现。此外还进一步介绍了实现准实时搜索的方法,展示了Solr的用法以及实现分布式搜索服务集群的方法。最后介绍了在...
本系列文章将详细描述几乎最新版本的Lucene的基本...Lucene学习总结之二:Lucene的总体架构 http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623596.html Lucene学习总结之三:Lucene的索引文件格式(1) ...
Lucene创建与搜索索引。个人做的流程总结。
我学习搜索引擎时的lucene总结,有doc格式,还有chm格式的可方便查看
Lucene总结..搜索的好工具.关于索引的建立等等
本书总结搜索引擎相关理论与实际解决方案,并给出了Java实现,其中利用了流行的开源项目Lucene和Solr,而且还包括原创的实现。本书主要包括总体介绍部分、爬虫部分、自然语言处理部分、全文检索部分以及相关案例分析...
本资源有三个内容: 电子书《搜索引擎--原理、技术与系统》 和两个网友的lucene学习分析资源。