Lucene全文检索

点击量:59

ES,Solar都是基于lucene实现,.本篇主要记录一部分的luceneAPI

全文检索

全文检索:将非结构化的数据先建立索引,再根据索引进行搜索的过程.只针对大量数据的情况

1.数据类型

结构化:数据存储有规律 (数据库中的数据)

非结构化:数据存储无规律

2.数据搜索

顺序扫描法:eg.数据库无索引搜索

全文检索:索引(相当于目录)

3.应用场景

1. word文档内容搜索
2. 搜索引擎(全网搜索内容)
3. 站内搜索
4. 垂直领域搜索(在某个领域中搜索内容)
当SQL中使用like模糊查询时,建立索引的字段不会使用索引进行查询操作

4.全文检索

不再从数据库查询数据,从自建的索引库中搜索

底层:lucene 实现;solr es

Lucene

Lucene是java中全文检索技术的底层,是一个开源代码的搜索引擎工具包

1.搜索方式

1. 顺序扫描法

2. 倒排索引扫描法

2.Lucene的API创建索引

导入相关依赖

lucene-analyzers-commons 默认分词器

lucene-core 核心库

commons-io 文件IO操作库

lucene-querypaser 查询解析器

lucene-highlighter 字段高亮显示

2.1基于lucene提供的api实现建立索引操作

创建索引需要用户自己建立文档字段,并指定索引的输出目录

Field字段类型时不确定的,因此提供了不同的子类,来应对不同的字段

如果一个字段要显示到最终的结果中,那么一定要存储,否则不存储

 @Test
public void createIndex()throws Exception{

//指定索引要存放的位置
FSDirectory indexDir = FSDirectory.open(new File("F:\\LUCENE_INDEX"));

//创建分词器对象(此处可替换为其他分词器)
StandardAnalyzer standardAnalyzer = new StandardAnalyzer();

//创建索引写入配置对象   参数(分词器版本号,分词器对象)
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, standardAnalyzer);


       

//创建索引写入器   参数(输出文件夹,配置对象)
IndexWriter indexWriter = new IndexWriter(indexDir, indexWriterConfig);

       
//准备索引库数据源 获取数据源目录
File fileDir = new File("F:\\LUCENE_TEST");
//获取文件数组
File[] files = fileDir.listFiles();
   
//批量将文件的内容添加进document,并依此创建索引
for (File file : files) {
   //创建文档对象
   Document document = new Document();
   //设置文档对象域字段内容
   //参数一:字段名称 参数二:字段内容 参数三:是否存储
   //TextField 字段默认分词
   document.add(new TextField("fileName",file.getName(), Field.Store.YES));
   document.add(new TextField("Content", FileUtils.readFileToString(file), Field.Store.YES));
   //StringField域字段类型,默认是不分词存储
   document.add(new StringField("filePath", file.getPath(), Field.Store.YES));
   //索引库添加文档
   indexWriter.addDocument(document);
}



//执行索引写入
indexWriter.commit();

//关闭索引写入器
indexWriter.close();
}

3.查询索引数据

* 不限字符个数匹配

? 只匹配一个字符

////标准分词器会屏蔽没有实际搜索意义的词汇, is this ...

@Test
public void test2() throws Exception {

//设置索引所在的位置
FSDirectory fsDirectory = FSDirectory.open(new File("F:\\LUCENE_INDEX"));

//创建索引读取器,并传入索引位置
DirectoryReader reader = DirectoryReader.open(fsDirectory);

//创建索引搜索器
IndexSearcher indexSearcher = new IndexSearcher(reader);

//创建分词器对象(此处可替换为第三方分词器)
StandardAnalyzer standardAnalyzer = new StandardAnalyzer();

//创建查询解析器   参数(要搜索的字段,分词器)
QueryParser parser = new QueryParser("fileName", standardAnalyzer);

//创建查询对象,并传入查询字段和参数(Query有多种搜索类型的子类)
Query query = new WildcardQuery(new Term("Content", "lizhihang"));

//执行搜索 参数(查询对象,前N条数据)
TopDocs search = indexSearcher.search(query, 10);

System.out.println("搜索到" + search.totalHits + "条数据");

ScoreDoc[] scoreDocs = search.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
//取出当前的文档的编号
int doc = scoreDoc.doc;
   
Document document = reader.document(doc);
   
System.out.println(document.get("fileName"));
System.out.println(document.get("Content"));
System.out.println("得分" + scoreDoc.score);
}
   
}
多种搜索类型
//基于词条搜索
Query query = new TermQuery(new Term("fileName","传智播客"))

//模糊查询 * 任意多个字符 ? 任意一个字符
WildcardQuery query = new WildcardQuery(new Term("fileName","传智播?"));

//相似度查询 一般针对英文 修改搜索内容不超过2次还原成词条,即可以匹配搜索
FuzzyQuery query = new FuzzyQuery(new Term("fileName","Lucene"))
   
//数值范围匹配
//参数1:查询的域,参数2:起始字节数值,参数3:结束字节数值,参数4:包含起始,参数5:包含结束
NumericRangeQuery<Long> query = NumericRangeQuery.newLongRange("fileSize", 0L, 50L, true, true)
   
   
//多条件组合查询
BooleanQuery query = new BooleanQuery();
TermQuery query1 = new TermQuery(new Term("fileName", "传智播客"));
TermQuery query2 = new TermQuery(new Term("fileName", "阴阳师"));
//MUST必须满足 SHOULD可以满足 MUST_NOT一定不满足
query.add(query1, BooleanClause.Occur.MUST);
query.add(query2, BooleanClause.Occur.MUST_NOT);*
   
   
//单字段域解析查询   从单独的字段中查询,如 fileName || content || desc
String queryStr="传智播客是一家不错的IT培训机构lucene";
//使用ik分词器分词 一定与创建索引时使用的分词器一致
Analyzer analyzer = new IKAnalyzer();
QueryParser parser = new QueryParser("fileName",analyzer);
Query query = parser.parse(queryStr);*/

   
//多字段域解析查询 从多个字段中查询,即查找fileName又查找contnet
String queryStr="传智播客是一家不错的IT培训机构lucene";
//使用ik分词器分词 一定与创建索引时使用的分词器一致
Analyzer analyzer = new IKAnalyzer();
//多字段域解析对象
MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[]{"fileName","fileContent"},analyzer);
Query query = parser.parse(queryStr);

4.删除索引数据

全部删除

基于词条删除

基于查询删除

@Test
public void delelteIndexTest() throws IOException {
//准备索引库目录位置
FSDirectory directory = FSDirectory.open(new File("F:\\index89"));
//分词器,需要对文档内容分词 Lucene默认分词器
//Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_4_10_3);
//分词器 没两个字组一个词
//Analyzer analyzer = new CJKAnalyzer(Version.LUCENE_4_10_3);
//使用ik分词器分词
Analyzer analyzer = new IKAnalyzer();

//索引库写对象的配置信息
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
//1、创建写入索引库对象
IndexWriter indexWriter = new IndexWriter(directory,config);

//删除索引库文档对象 慎用
//删除所有文档
//indexWriter.deleteAll();
//基于词条删除
//indexWriter.deleteDocuments(new Term("fileName","传智播客"));
//基于查询删除
NumericRangeQuery<Long> query = NumericRangeQuery.newLongRange("fileSize", 0L, 50L, true, true);
indexWriter.deleteDocuments(query);
//提交操作文档数据
indexWriter.commit();
//释放资源
indexWriter.close();

}

  1. 修改索引数据

    逻辑:先将满足修改条件的文档删除,再将新增参数尔赋予新的文档对象

2.中文分词器

使用第三方分词器: IKAnalyzer

优势:很好的支持中英文分词,可以动态的扩展词汇和动态的停用词汇

需要配置文件:加载扩展词和停用词


感谢您的阅读
文章由作者个人总结,欢迎指出文章错误



上一篇:Kotlin(2)-类与对象

下一篇:使用java操作阿里大于的短信业务