lucene7.5学习笔记(三)文章相似性检索

时隔四个月我又回来继续填之前说好要写的关于lucene的坑了,按照之前的安排在第三节中应该是介绍如何通过lucene实现搜索词提示的,但是目前我所实现的搜索词提示过于简单,连基本的根据拼音进行中文提示都无法实现,因此这里我改一下顺序先介绍一下如何通过lucene实现文章的相似性检索。

文章的相似性检索就是对比两篇文章的相似程度,这个功能的应用非常广泛,例如在亚马逊上通过对比得知A和B两本书的十分相似,那么自然而然的可以想到给购买的A的读者推荐B时读者购买的概率会很大。目前运用比较多的实现相似性检索的方法是通过TF-IDF算法计算文章的关键字向量,然后通过余弦相似度方法计算文章间的相似值(这只是一种目前比较常用也比较简单的方法,具体lucene7.5中是否就是用了这种方法来实现的我也不知道,这里提一下只是因为我想卖弄一下而已)。

通过lucene7.5进行相似性检索首先要对需要进行相似性计算的数据建立向量索引,具体代码如下。

public static void createIndex(String value) throws IOException {String indexDirectoryPath = "D:/similar/";// 读取需要索引的文件到Lucene的目录类中,新版的Lucene只支持IO2中的Path类型的变量了。Directory indexDirectory = FSDirectory.open(Paths.get(indexDirectoryPath));// 创建分词器,这里使用的是SmartChineseAnalyzer分词器,可以根据具体需要使用其他分词器。Analyzer analyzer = new SmartChineseAnalyzer();// 新版的Lucene中索引创建类只接收IndexWriterConfig配置。IndexWriterConfig iwc = new IndexWriterConfig(analyzer);IndexWriter writer = new IndexWriter(indexDirectory, iwc);try {FieldType fieldType = new FieldType();Document doc = new Document();fieldType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);fieldType.setStored(true);fieldType.setTokenized(true);fieldType.setStoreTermVectors(true);fieldType.setStoreTermVectorPositions(true);fieldType.setStoreTermVectorOffsets(true);fiedType.freeze();Field docField = new Field("title", value, fieldType);doc.add(docField);writer.addDocument(doc);} finally {writer.close();}
}

上述代码中实现了将参数value的值添加到一个名叫title的field中,这个field是向量型的field。

实现了数据的索引,接下来就可以实现相似性的查询了,具体代码如下。

public static void search(int docId) throws IOException {Directory directory = FSDirectory.open(Paths.get("D:/similar/"));IndexReader reader = DirectoryReader.open(directory);IndexSearcher searcher = new IndexSearcher(reader);MoreLikeThis mlt = new MoreLikeThis(reader);mlt.setFieldNames(new String[]{"title"});//最少的词频 mlt.setMinTermFreq(2);//最多的查询词数目mlt.setMaxQueryTerms(Integer.MAX_VALUE);//词至少在这么多篇文档中出现mlt.setMinDocFreq(5);Query query = mlt.like(docId);TopDocs hits = searcher.search(query, 100);for(ScoreDoc scoreDoc : hits.scoreDocs) {System.out.println("Similar: " + scoreDoc);}reader.close();
}

上述代码中有几点需要注意一下,首先setMinTermFreq、setMaxQueryTerms和setMinDocFreq设置的是查询相关阈值的配置,可以通过调整阈值来对你的相似性的要求进行修改。具体来说setMinTermFreq设定的是关键字在文章中最少出现的次数,在上面的代码中设置的是2,即如果一个词在文章中只出现了一次那么这个词将不作为关键字,在相似性比对的时候将忽略这个词。setMaxQueryTerms的用处我不是很清楚。setMinDocFreq是设置一个词在最少要在多少篇文章中出现,这里设置的是5,即表示一个词最少要在5篇文章中出现才会在相似性比对中使用,如果你的数据量较少建议将这个值设置的小一点,如2或者3。最后还要注意一点,在做相似性检索的时候检索条件是lucene自动生成的document的id,这个id是lucene自动生成的。在具体的实现中我们往往是无法提前知晓document的id的,因此在具体实现时我会在document中加入一个我自己的id值,通常就是数据库中的主键id,然后在做相似性检索前先用自己的id来定位document并获取docId,然后通过docId来进行相似性检索。

相似性检索到这里就完了,最近还在研究基于lucene的查询提示功能,发现lucene的提词还是比较难实现的,主要有几个问题,一个是拼音不支持,还有一个是提示时是直接提示没有做分词,不能实现像百度那样代空格的提示,还需要继续研究。目前拼音的问题已经解决,分词提示现在有两个思路,还需进一步验证,如最终两个思路都无法解决问题我会先把实现拼音提词的方法发上来。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部