You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Lucene 9.5.0:不分词存储下实现大小写不敏感搜索

解决Lucene大小写不敏感搜索问题(保留原字符串存储)

你的问题核心在于**KeywordAnalyzer不会对文本做大小写转换**:索引阶段存储的是原始大小写的John Smith,搜索阶段输入的john smith会被原样处理,导致两者无法匹配。以下是符合你需求的解决方案:

方案:自定义大小写不敏感的KeywordAnalyzer

我们需要一个既能保持不分词特性(和KeywordAnalyzer一致),又能自动处理大小写转换的分析器。可以通过KeywordTokenizer搭配LowerCaseFilter实现:

自定义Analyzer代码

static class CaseInsensitiveKeywordAnalyzer extends Analyzer {
    @Override
    protected TokenStreamComponents createComponents(String fieldName) {
        // 使用KeywordTokenizer保证不分词
        Tokenizer tokenizer = new KeywordTokenizer();
        // 添加LowerCaseFilter实现大小写统一转换
        TokenStream filter = new LowerCaseFilter(tokenizer);
        return new TokenStreamComponents(tokenizer, filter);
    }
}

修改后的完整示例代码

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.KeywordTokenizer;
import org.apache.lucene.analysis.core.LowerCaseFilter;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.IOException;
import java.nio.file.Paths;

public class LuceneExample {
    public static void main(String[] args) throws IOException, ParseException {
        // 使用自定义的大小写不敏感KeywordAnalyzer
        Analyzer analyzer = new CaseInsensitiveKeywordAnalyzer();
        String indexDirectoryPath = "/temp/test";
        Directory directory = FSDirectory.open(Paths.get(indexDirectoryPath));
        
        // 索引阶段配置
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        IndexWriter writer = new IndexWriter(directory, config);
        
        Document doc = new Document();
        // 保留原始大小写存储
        doc.add(new StringField("name", "John Smith", Field.Store.YES));
        writer.addDocument(doc);
        writer.close();
        
        // 搜索阶段配置
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        QueryParser parser = new QueryParser("name", analyzer);
        // 输入任意大小写的搜索词都能匹配
        Query query = parser.parse("john smith");
        TopDocs results = searcher.search(query, 10);
        
        for (int i = 0; i < results.scoreDocs.length; i++) {
            Document hitDoc = searcher.doc(results.scoreDocs[i].doc);
            // 输出原始大小写的字符串:John Smith
            System.out.println(hitDoc.get("name"));
        }
        
        reader.close();
        directory.close();
    }

    static class CaseInsensitiveKeywordAnalyzer extends Analyzer {
        @Override
        protected TokenStreamComponents createComponents(String fieldName) {
            Tokenizer tokenizer = new KeywordTokenizer();
            TokenStream filter = new LowerCaseFilter(tokenizer);
            return new TokenStreamComponents(tokenizer, filter);
        }
    }
}

关键说明

  1. 索引逻辑:自定义分析器会将文本转换为小写存入索引,但StringField的Field.Store.YES会保留原始大小写的字符串,满足你存储需求。
  2. 搜索逻辑:搜索词会被自动转换为小写,和索引中的小写文本匹配,实现大小写不敏感搜索。
  3. 一致性要求:索引和搜索必须使用同一个自定义分析器,否则会出现匹配失效问题。

内容的提问来源于stack exchange,提问作者TheHydGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 08:25:20