lucene使用

本文详细介绍了Lucene全文检索技术的原理与应用,包括结构化与非结构化数据的概念,全文检索的流程,如创建索引、分析文档、查询索引等。特别关注了IK分词器的使用方法及代码实现细节。
一 概述
   结构化数据    格式和长度固定,比如数据库表
   非结构化数据  格式和长度不固定,比如word 
   全文检索      针对非结构化数据,采用先建立索引,然后再索引的基础上进行查询
   java全文检索技术lucene  全文检索的工具包 
   应用场景:针对大数据量的情况下,对数据的模糊查询或者自然语言的检索。
二 创建索引
        1 获取原始文档  爬虫Nutch jsoup
        2 创建文档对象   document 相当于表中一条记录   field 属于document 相当于表中的字段   field中存储内容
                filed的属性判断原则:
                是否需要分词 需要在也页面进行查询的大部分都需要进行分词,除了一些拥有特殊业务含义,分割后会失去原有含义的不需要进行分词。比如订单编号,身份证号。
                是否需要索引 需要在页面进行查询的就需要进行索引
                是否需要存储 需要在页面显示的就需要存储
        3 分析文档 
                对存放在field中的内容进行分析,得到term列表。
                过程:对原始文档提取单词、将字母转为小写、去除标点符号、去除停用词
        4 创建索引
       对term列表进行索引,每个term执行文档的id列表。  
三 查询索引
        1 查询接口
        2 创建查询
        3 执行查询
        4 渲染结果
四 IK分词器
    ik分词器即支持中文也支持英文。
        使用方法:
        第一步:把jar包添加到工程中
        第二步:把配置文件和扩展词典和停用词词典添加到classpath下
        注意:mydict.dic和ext_stopword.dic文件的格式为UTF-8,注意是无BOM 的UTF-8 编码。
        分词器的应用时机:        创建索引时和查询索引时针对查询内容先进行分词。
五 代码实现
[Java]  纯文本查看  复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
//创建索引
     public void createIndex() throws Exception{
         IndexWriter indexWriter = getIndexWriter();
         File sourceFile = new File( "E:\\项目二\\lucene\\day06\\资料\\searchsource" );
         for (File file :sourceFile.listFiles() ) {
             String fileName = file.getName();
             String filePath = file.getPath();
             long size = FileUtils.sizeOf(file);
             String fileContent = FileUtils.readFileToString(file);
             Document document = new Document();
             TextField fileNameField = new TextField( "name" , fileName, Store.YES);
             StoredField pathField = new StoredField( "path" , filePath);
             LongField sizeField = new LongField( "size" , size, Store.YES);
             TextField contentFeild = new TextField( "content" ,fileContent,Store.NO);
             
             document.add(fileNameField);
             document.add(pathField);
             document.add(sizeField);
             document.add(contentFeild);
             indexWriter.addDocument(document);
         }
         indexWriter.close();
     }
     
     //查询索引
     public void queryIndex() throws Exception{
         Directory directory = FSDirectory.open( new File( "E:\\index" ));
         IndexReader indexReader = DirectoryReader.open(directory);
         IndexSearcher indexSearcher = new IndexSearcher(indexReader);
         //term查询相当于等值查询
         Query query = new TermQuery( new Term( "name" , "lucene" ));
         TopDocs topDocs = indexSearcher.search(query , 10 );
         for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
             int id = scoreDoc.doc;
             Document document = indexSearcher.doc(id);
             System.out.println(document.getField( "name" ));
             System.out.println(document.getField( "path" ));
             System.out.println(document.getField( "content" ));
             System.out.println(document.getField( "size" ));
         }
         
         indexReader.close();
     }
     
     // 添加文档
     public void addDocument() throws Exception {
         IndexWriter indexWriter = this .getIndexWriter();
         Document document = new Document();
         TextField fileNameField = new TextField( "name" , "测试文档.txt" , Store.YES);
         StoredField pathField = new StoredField( "path" , "c:\\temp" );
         LongField sizeField = new LongField( "size" , 1111 , Store.YES);
         document.add(fileNameField);
         document.add(pathField);
         document.add(sizeField);
         indexWriter.addDocument(document);
         indexWriter.close();
     }
     
     // 根据query删除文档
     public void deleteByQuery() throws Exception {
         IndexWriter indexWriter = this .getIndexWriter();
         Query query = new TermQuery( new Term( "name" , "测试" ));
         
         indexWriter.deleteDocuments(query);
         indexWriter.close();
     }
     
     // 删除全部文档
     public void deleteAll() throws Exception {
         IndexWriter indexWriter = this .getIndexWriter();
         
         indexWriter.deleteAll();
         indexWriter.close();
     }
     
     //更新文档
     //先删除,然后再添加
     public void update() throws Exception{
         IndexWriter indexWriter = this .getIndexWriter();
         Term term = new Term( "name" , "spring" );
         Document doc = new Document();
         TextField fileNameField = new TextField( "name" , "测试文档111.txt" , Store.YES);
         StoredField pathField = new StoredField( "path" , "c:\\temp" );
         LongField sizeField = new LongField( "size" , 1111 , Store.YES);
         doc.add(fileNameField);
         doc.add(pathField);
         doc.add(sizeField);
         indexWriter.updateDocument(term, doc);
         indexWriter.close();
     }
     
     //创建索引写入器
     private IndexWriter getIndexWriter() throws IOException {
         //指定索引库存放路径 ,可以存放在内存也可以存放在硬盘,一般存放在硬盘上。
         Directory directory = FSDirectory.open( new File( "E:\\index" ));
         //创建ik分词器 ik分词器即支持中文也支持英文
         Analyzer analyzer = new IKAnalyzer();
         IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
         //创建索引写入器
         IndexWriter indexWriter = new IndexWriter(directory, config);
         return indexWriter;
     }
Elasticsearch 使用 Lucene 作为其核心搜索引擎库,Lucene 在构建和维护索引以及执行搜索操作时会涉及多种内存使用情况。以下是与 Elasticsearch 中 Lucene 内存使用相关的关键点: ### 1. 堆内内存(Heap Memory)使用 Lucene 的一些组件直接依赖于 JVM 堆内存来运行,例如: - **文档字段的缓存**:在索引创建过程中,文档字段会被存储或分析,并可能占用堆内存。 - **查询缓存(Query Cache)**:Elasticsearch 会缓存频繁使用的过滤器查询结果,以提升后续相同查询的性能,这部分缓存数据存储在堆内存中。 - **字段值缓存(Field Value/Doc Values Cache)**:当需要对字段进行排序、聚合或脚本计算时,Elasticsearch 会加载字段值到内存中。 如果堆内存配置不足,可能会导致垃圾回收(GC)频率增加,甚至出现 OutOfMemoryError [^1]。 ### 2. 堆外内存(Off-Heap Memory)使用 Lucene 和 Elasticsearch 还利用堆外内存来减少 JVM 垃圾回收的压力。堆外内存通常用于: - **倒排索引结构(Term Dictionary、Postings List 等)**:Lucene 使用 MMapDirectory 或其他基于堆外内存的 Directory 实现将索引文件映射到内存中。 - **FST(Finite State Transducer)**:用于自动补全建议和前缀搜索的数据结构,通常也驻留在堆外内存中。 - **Lucene 的 IndexReader 缓存**:为了加快检索速度,IndexReader 可能会缓存部分索引元信息在堆外。 堆外内存不受 JVM GC 控制,因此可以更高效地处理大规模数据集 [^1]。 ### 3. 内存调优设置 Elasticsearch 提供了若干配置选项来优化 Lucene 的内存使用: - `index.memory.index_writer.max_memory`:控制索引写入器使用的最大堆外内存。 - `indices.memory.heap_buffer_size`:限制堆上缓冲区的大小。 - `index.cache.field.type`:设置字段缓存类型为堆或堆外。 - `indices.query.cache.size`:调整查询缓存的大小比例,避免占用过多堆内存。 此外,还可以通过监控工具如 `_nodes/stats` API 来查看 Lucene 各类缓存的使用情况,包括堆内外内存分配 [^1]。 ### 4. 性能影响与监控 Lucene 内存使用不当可能导致以下问题: - 高堆内存使用引发频繁 Full GC,降低集群稳定性。 - 堆外内存泄漏或配置过小会影响搜索性能。 - 索引构建阶段内存不足会导致索引失败。 可以通过如下方式监控 Lucene 内存使用情况: ```bash GET _nodes/stats/indices/query_cache,field_data,request_cache,memory ``` ### 示例代码:获取节点级 Lucene 内存统计 ```json { "nodes": { "node_id": { "indices": { "query_cache": { "memory_size_in_bytes": 1048576, "total_size_in_bytes": 1048576 }, "field_data": { "memory_size_in_bytes": 2097152 } } } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值