- 2024-02-23 17:04:03
- 337 热度
- 0 评论
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
本示例实用junit来测试,使用了3.5.0版本,实用Maven来引入,POM文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacui.lucene</groupId> <artifactId>zlucene</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>zlucene</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
建立索引的步骤
1.创建Directory
2.创建IndexWriter
3.创建Document对象
4.为Document添加Field
Directory是存放索引的位置,是一个公用的对象,所以写在初始化里面。
private static Directory directory = null; @Before public void init() throws Exception { directory = FSDirectory.open(new File("D:/tmp/lucene")); }
如果是在内存中创建,实用以下代码:
Directory directory = new RAMDirectory();
然后编写添加索引的代码
@Test public void createIndex() throws Exception { IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)); IndexWriter writer = null; writer = new IndexWriter(directory, iwc); Document doc = null; File f = new File("D:/data/test"); for(File file : f.listFiles()){ doc = new Document(); doc.add(new Field("context", new FileReader(file))); doc.add(new Field("fileName",file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED)); doc.add(new Field("filePath",file.getPath(),Field.Store.YES,Field.Index.NOT_ANALYZED)); writer.addDocument(doc); } writer.close(); log.debug("运行结束"); }
这里D:/data/test文件夹下有很多log日志文件,遍历这个目录,把文件的名称、路径,和内容放到Lucene中。
文档Document和域Field的关系
文档Document相当于关系表中的每一条记录,域相当于表中的每一个字段,先创建文档,之后为文档添加域.
域存储选项和域索引选项,均需要在域添加的时候设置
存储域选项
Field.Store.YES表示把这个域中的内容完全存储到文件中,方便进行文本的还原
Field.Store.NO表示把这个域中的内容不存储到文件中,但是可以被索引,此时内容无法还原(即无法document.get());
索引域选项
Field.Index.ANALYZED:进行分词和索引,适用于标题和内容等
Field.Index.NOT_ANALYZED:进行索引,但是不进行分词,像身份证号,姓名,ID等,适用于精确索索
Field.Index.ANALYZED_NO_NORMS:进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息
Field.Index.NOT_ANALYZED_NO_NORMS:即不进行分词也不存储norms信息
Field.Index.NO:不进行索引
最佳实践
Field.Index.NOT_ANALYZED_NO_NORMS, Field.Store.YES标识符(主键,文件名),电话号码,身份证号,姓名,日期
Field.Index.ANALYZED, Field.Store.YES文档标题和摘要
Field.Index.ANALYZED, Field.Store.NO文档正文
Field.Index.NO,Field.Store.YES文档类型,数据库主键(不进行索引)
Field.Index.NOT_ANALYZED,Field.Store.NO 隐藏关键字
搜索操作的步骤:
1.创建Directory
2.创建IndexReader
3.根据IndexReader创建IndexSearcher
4.创建搜索的Query
5.根据Searcher搜索并且返回TopDocs
6.根据TopDocs获取ScoreDoc对象
7.根据Seacher和ScoreDoc对象获取具体的Document对象
8.根据Document对象获取需要的值
9.关闭IndexReader
@Test public void searchIndex() throws Exception { IndexReader reader = null; IndexSearcher search = null; reader = IndexReader.open(directory); search = new IndexSearcher(reader); QueryParser parser = new QueryParser(Version.LUCENE_35, "context", new StandardAnalyzer(Version.LUCENE_35)); Query query = parser.parse("com.lelife.solrclient.job.SyschronizedPromotion"); TopDocs tds = search.search(query, 10); ScoreDoc[] sds = tds.scoreDocs; if(null!=sds&&sds.length>0){ for(ScoreDoc sd : sds){ Document d = search.doc(sd.doc); log.debug(d.get("fileName") + "[" + d.get("filePath") + "]"); } }else{ log.debug("没有匹配的文档"); } search.close(); reader.close(); log.debug("运行结束"); }
这里查询内容中包含com.lelife.solrclient.job.SyschronizedPromotion的文件,并打印文件名称和位置。
删除文档操作
删除有多种方式,精确和查询式删除,或者全删。
@Test public void deleteIndex() throws Exception { IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)); IndexWriter writer = null; writer = new IndexWriter(directory, iwc); writer.deleteAll(); // writer.deleteDocuments(new Term("fileName","lelifeclient.log")); // QueryParser parser = new QueryParser(Version.LUCENE_35, "context", new StandardAnalyzer(Version.LUCENE_35)); // Query query = parser.parse("com.lelife.solrclient.job.SyschronizedPromotion"); // writer.deleteDocuments(query); writer.close(); log.debug("运行结束"); }
indexWriter.deleteDocuments()文档并不会完全被删除,而是存储在一个回收站中,我们可以编写查询类来进行查询。
以下代码查看当前的索引情况:
@Test public void showIndex() throws Exception { IndexReader indexReader = IndexReader.open(directory); log.debug("总存储量:" + indexReader.maxDoc()); log.debug("存储的文档数:" + indexReader.numDocs()); log.debug("被删除的文档:" + indexReader.numDeletedDocs()); }
恢复被删除的文档:
使用IndexReader可以有效的恢复删除到回收站的文档。
@Test public void recoveryIndex() throws Exception { IndexReader indexReader = IndexReader.open(directory,false); indexReader.undeleteAll(); indexReader.close(); }
清空回收站文档:
如果要清空回收站中的内容,需要使用IndexWriter中的forceMergeDeletes()方法。
@Test public void forceDelete() throws Exception{ IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)); IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); indexWriter.forceMergeDeletes(); indexWriter.close(); }
更新文档:
Luence并没有提供更新,这里的更新操作其实是先删除再添加的操作合集。
@Test public void updateIndex() throws Exception{ IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)); IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig); Document doc = null; File f = new File("D:/data/test"); for(File file : f.listFiles()){ doc = new Document(); doc.add(new Field("context", new FileReader(file))); doc.add(new Field("fileName",file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED)); doc.add(new Field("filePath",file.getPath(),Field.Store.YES,Field.Index.NOT_ANALYZED)); indexWriter.updateDocument(new Term("fileName",file.getName()), doc); } indexWriter.close(); log.debug("运行结束"); }
结束。
- Spring(403)
- Boot(208)
- Spring Boot(187)
- Java(82)
- Cloud(82)
- Spring Cloud(82)
- Security(60)
- Spring Security(54)
- Boot2(51)
- Spring Boot2(51)
- Redis(31)
- SQL(29)
- Mysql(25)
- IDE(24)
- Dalston(24)
- JDBC(22)
- IDEA(22)
- mongoDB(22)
- MVC(22)
- Web(21)
- CLI(20)
- Alibaba(19)
- SpringMVC(19)
- SpringBoot(17)
- Docker(17)
- Eclipse(16)
- Vue(16)
- Git(16)
- JPA(15)
- Apache(15)
- ORA(15)
- Oracle(14)
- jdk(14)
- Tomcat(14)
- Linux(14)
- HTTP(14)
- Mybatis(14)
- XML(13)
- JdbcTemplate(13)
- OAuth(13)
- Nacos(13)
- Pro(13)
- Data(12)
- JSON(12)
- OAuth2(12)
- stream(11)
- int(11)
- Myeclipse(11)
- not(10)
- Bug(10)
- maven(9)
- Map(9)
- Hystrix(9)
- ast(9)
- APP(8)
- Bit(8)
- API(8)
- session(8)
- Window(8)
- Swagger(8)
- Github(7)
- JavaMail(7)
- Cache(7)
- File(7)
- IntelliJ(7)
- mail(7)
- windows(7)
- too(7)
- HTML(7)
- and(6)
- star(6)
- Excel(6)
- Log4J(6)
- pushlet(6)
- apt(6)
- read(6)
- Freemarker(6)
- WebFlux(6)
- JSP(6)
- Bean(6)
- error(6)
- nginx(6)
- Server(6)
- jar(6)
- ueditor(6)
- ehcache(6)
- UDP(6)
- RabbitMQ(6)
- PHP(5)
- Struts(5)
- string(5)
- Syntaxhighlighter(5)
- script(5)
- Tool(5)
- Controller(5)
- swagger2(5)
- ldquo(5)
- input(5)
- Servlet(5)
- Config(5)