Lucene 8(Java)分析后词干提取示例及实操问询
嘿,我来帮你搞定Lucene 8里的词干提取匹配问题!你的需求是让输入"Burger"或"Burgers"时能互相匹配,核心就是让索引和查询阶段都用EnglishAnalyzer——它自带词干提取逻辑,能把不同形式的单词归一化成同一个词干,这样就能实现你要的模糊匹配效果了。
核心思路
EnglishAnalyzer在Lucene 8里已经集成了PorterStemFilter(词干提取器),同时还包含分词、小写转换、停用词过滤等流程。不管是索引时的"Burgers",还是查询时的"Burger",经过它处理后都会变成相同的词干(比如burger),这样就能命中对应的文档了。
注意:一定要保证索引和查询用同一个分析器,不然词干不一致就匹配不到哦!
索引代码修改
你之前的索引代码只写了添加TextField的部分,我把完整的索引创建流程补上,重点是把StandardAnalyzer换成EnglishAnalyzer:
import org.apache.lucene.analysis.en.EnglishAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.FSDirectory; import java.io.File; import java.io.IOException; // 假设这是你的索引创建方法 public void createIndex(File indexDir) throws IOException { // 使用EnglishAnalyzer创建索引配置 EnglishAnalyzer analyzer = new EnglishAnalyzer(); IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); try (IndexWriter writer = new IndexWriter(FSDirectory.open(indexDir.toPath()), config)) { // 模拟你的业务数据,替换成实际从jsonObject获取的name String name = (String)jsonObject.get("name"); Document doc = new Document(); // 添加TextField,会自动用配置的EnglishAnalyzer处理 doc.add(new TextField("name", name, Field.Store.YES)); writer.addDocument(doc); } }
查询代码修改
把查询时的StandardAnalyzer换成EnglishAnalyzer,这样查询文本也会被词干提取:
import org.apache.lucene.analysis.en.EnglishAnalyzer; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.queryparser.classic.QueryParser; import java.io.File; import java.io.IOException; // 假设这是你的查询方法 public void searchIndex(File indexDir) throws Exception { try (IndexReader indexReader = DirectoryReader.open(FSDirectory.open(indexDir.toPath()))) { IndexSearcher indexSearcher = new IndexSearcher(indexReader); // 关键:用EnglishAnalyzer创建QueryParser EnglishAnalyzer analyzer = new EnglishAnalyzer(); QueryParser nameParser = new QueryParser("name", analyzer); // EnglishAnalyzer会自动处理小写转换,无需手动调用toLowerCase() Query nameQuery = nameParser.parse(textField.getText()); TopDocs topDocs = indexSearcher.search(nameQuery, 50); // 后续处理结果的逻辑,比如遍历topDocs.scoreDocs获取文档 // ... } }
额外说明
- 自动小写转换:
EnglishAnalyzer已经包含了LowerCaseFilter,所以你可以去掉之前手动调用的textField.getText().toLowerCase()步骤,简化代码。 - 停用词自定义:
EnglishAnalyzer默认会过滤常见停用词(比如"the"、"a"),如果你的场景不需要,可以创建分析器时传入空的停用词集合:// 禁用停用词过滤 EnglishAnalyzer analyzer = new EnglishAnalyzer(CharArraySet.EMPTY_SET);
这样修改后,不管你索引的是"Burgers"还是查询时输入"Burger",都能匹配到对应的文档啦!
内容的提问来源于stack exchange,提问作者Nash103
相关产品推荐
相关产品推荐

