您的位置:首页 > 其它

Lucene简单使用一之文件索引

2017-09-20 11:36 477 查看
lucene做文件索引

最近公司的一个基于开源项目要做的优化,查找目录下文件目录增加一个关键字查询,直接使用目录getchild考虑到文件数量大后的性能,领导让加个文件索引。

文件索引,这里我考虑的这个关键字查询需要匹配的无非就是3个方面,文件名包含、文件路径包含、文件内容包含。

来来,我们先看下界面:



红框线就是优化新增的,李彪上也增加了一列展示文件路径,这里原来是只展示当前目录下的文件与目录的,所以没有这一列,现在为了好理解,方便查找文件,增加的这一列。

言归正传,首先肯定是索引的生成,不然查询个屁啊。要说到索引的生成那就不得不说到分词器了。以为第一次使用,这里也就简单说说几个常用的分词器。

一、WhitespaceAnalyzer

以空格作为切词标准,不对语汇单元进行其他规范化处理。很明显这个实用英文,单词之间用空格。

二、SimpleAnalyzer

以非字母符来分割文本信息,并将语汇单元统一为小写形式,并去掉数字类型的字符。很明显不适用于中文环境。

三、StopAnalyzer

停顿词分析器会去除一些常有a,the,an等等,也可以自定义禁用词,不适用于中文环境

四、StandardAnalyzer

标准分析器是Lucene内置的分析器,会将语汇单元转成小写形式,并去除停用词及标点符号,很明显也是不适合于中文环境

五、CJKAnalyzer

中日韩分析器,能对中,日,韩语言进行分析的分词器,但是对中文支持效果一般,一般不用

六、SmartChineseAnalyzer

对中文支持稍好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理
学习完理论,我们直接上代码实战。(涉及公司资源,就贴下lucene技术相关的核心代码吧,见谅)
//获取配置lucene索引存放路径
String path = realPathResolver.get(Constants.LUCENE_PATH);
//获取lucene的文件系统对象
Directory dir = new SimpleFSDirectory(new File(path));

boolean exist = IndexReader.indexExists(dir);

// 自定义停用词

String[] self_stop_words = { ".", "/", ":" };

CharArraySet cas = new CharArraySet(30, true);

for (int i = 0; i < self_stop_words.length; i++) {

cas.add(self_stop_words[i]);

}

// 加入系统默认停用词

Iterator<?> itor = StandardAnalyzer.STOP_WORDS_SET.iterator();

while (itor.hasNext()) {

cas.add(itor.next());

}

IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(
Version.LUCENE_30,cas), !exist, IndexWriter.MaxFieldLength.LIMITED);
try {
if (exist) {

//存在的就删除(方便重新生成,索引优化)
LuceneTemplate.delete(siteId, root, writer);
}

//重新生成索引
Integer lastId = luceneContentDao.templateIndex(writer, siteId,root );
writer.optimize();
return lastId;
} finally {
writer.close();
}
templateIndex方法:
List<Tpl> childLs = (List<Tpl>) tplManager.getChild(root);
if(!CollectionUtils.isEmpty(childLs)) {
for(Tpl tmpTpl:childLs) {
String tplPath = tmpTpl.getPath();
String tplFileName = tmpTpl.getFilename();
log.debug("----模板搜索------tplPath:"+tplPath+"--------------tplFileName:"+tplFileName);
writer.addDocument(LuceneTemplate.createDocument(tmpTpl,siteId,root));
//生成子目录文件的索引--迭代
if(tmpTpl.isDirectory()) {
templateIndex( writer, siteId, tplPath + "/" + tplFileName);
}
}
}
return null;
createDocument:
public static Document createDocument(Tpl t, Integer siteId, String root) {
//Field.Store.YES保存、Field.Store.NO不保存
//Field.Index.NOT_ANALYZED索引不分词
Document doc = new Document();
doc.add(new Field(SITE_ID, siteId.toString(),
Field.Store.NO, Field.Index.NOT_ANALYZED));
doc.add(new Field(FILEPATH, t.getPath(),
Field.Store.YES, Field.Index.NOT_ANALYZED));
String fileName = t.getFilename();
//匹配文件名称
if(StringUtils.isNotBlank(fileName)) {
doc.add(new Field(FILENAME, t.getFilename(),
Field.Store.YES, Field.Index.NOT_ANALYZED));
}
//匹配内容
if(fileName.endsWith(".html")) {
doc.add(new Field(FILECONTENT, t.getSource(),
Field.Store.YES, Field.Index.NOT_ANALYZED));
}
//匹配目录路径

if(StringUtils.isNotBlank(root)) {
doc.add(new Field(ROOT, root,
Field.Store.NO, Field.Index.NOT_ANALYZED));
}
return doc;
}
到此索引生成的核心都贴完了,大家领会下,下面在来看看索引的使用
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);
}
if(StringUtils.isNotBlank(fileContent)) {
q = new WildcardQuery(new Term(FILECONTENT, "*"+fileContent+"*"));
bq.add(q, BooleanClause.Occur.SHOULD);
}
return bq;
}
看看查询出来的界面:



最后,留个问题给大家,索引的文件名称与路径我为什么要保存?????数据库里的数据做索引想想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: