Lucene搜索技术
1: 搜索技术概述
起步:Robot(比如抢票器)与spider(网络爬虫)的出现
发展:excite,galaxy,yahoo
繁荣:infoseek,altaVista,Google和baidu
2:搜索技术的使用原理
通过网略爬虫向各个网站进行资源搜罗,把搜索到的资源进过筛选保存到快照库,用索引进行搜索查询。
倒排索引就像一本书的目录,记录关键单词在文档中出现的位置,在搜索时会节省大量时间.
lucene是一种搜索技术的实现方式,通过倒排索引技术,提高检索速度,实现快速搜索
索引的查看工具可以使用LukeAll
3:索引的创建
pom.xml引入坐标依赖:
<dependencies> <!-- lucene核心库 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>4.10.4</version> </dependency> <!-- Lucene的查询解析器 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>4.10.4</version> </dependency> <!-- lucene的默认分词器库 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>4.10.4</version> </dependency> <!-- lucene的高亮显示 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>4.10.4</version> </dependency> <!-- Junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <!-- ik中文分词器 --> <dependency> <groupId>com.janeluo</groupId> <artifactId>ikanalyzer</artifactId> <version>2012_u6</version> </dependency> </dependencies> |
测试代码:
publicclass LuceneTest {
//创建索引 @Test publicvoid testCreateIndex() throws Exception{
//1.创建Document文档(相当于一条数据)-是一篇文章 Document document=new Document(); //在文档中加入Field字段 //1)业务编号:参数1:字段名字,参数2:字段值,参数3:是否存储 document.add(new LongField("id", 101, Store.YES)); //2)标题:TextField自动分词 document.add(new TextField("title", "世界很美好", Store.YES)); //3)作者:StringField不分词 document.add(new StringField("author", "小七", Store.YES)); //4)邮箱:只存储和显示,不能搜索,默认是Store.YES document.add(new StoredField("email", "[email protected]")); //5)内容:自动分词存储并能搜索 document.add(new TextField("content", "人人献出一点爱,这个世界将会更美好! World !", Store.YES)); //6):备注 document.add(new TextField("remark", "我是备注", Store.NO));
//2.准备索引写对象,写文档到索引 //创建索引存放目录对象 Directory directory=FSDirectory.open(new File("indexdir")); //索引的写的配置对象:参数1:lucene的版本,参数2:分词器,这里使用内置分词 IndexWriterConfig indexWriterConfig=new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
//创建一个写的对象:参数1:索引存放目录对象,参数2:建立索引的配置对象 IndexWriter indexWriter=new IndexWriter(directory, indexWriterConfig); //将上面准备的文档,写入索引中 indexWriter.addDocument(document); //5)提交事务(可以省略) // indexWriter.commit(); //6)释放资源 indexWriter.close(); directory.close(); } } 4. Analyzer分词器对象在Lucene索引的api中有个重要的对象叫Analyzer(分词器对象),该对象的主要作用是提供分词的算法,可以将文档中的字段的数据按照算法分词。Lucene内置英文分词器.
扩展词典和停用词典在更改时一定要UTF-8保存5.索引创建的工具类
6. 索引的基本查询 |
//各种常见查询规则测试
@Test
publicvoidtestManyQuery() throwsException{
//准备查询的关键字
String keyword="我是好人";
//准备Query(查询条件对象)
//Query
//创建一个查询解析器(查询条件创建对象-QueryBuilder对象)
//参数1:要查询的字段的名字,必须有才行
//参数2:分词器,在查询的时候,先将关键词分词,再搜索
// QueryParserqueryParser = new QueryParser("content",new IKAnalyzer());
// QueryParserqueryParser = new QueryParser("content",new StandardAnalyzer());
//解析(分词))后的查询对象
// Query query =queryParser.parse(keyword);
//词条精确匹配
Query query=null;
//规则1:精确匹配
//参数1:要匹配词条的字段的名称,参数2:关键字
query = new TermQuery(new Term("content",keyword));
//规则2:通配符匹配,在词条精确匹配的基础上,支持了通配符
//*:0或N个字符, ?:代表1个字符
query = new WildcardQuery(new Term("content","*"+keyword+"*"));
//规则3:模糊匹配,相似度匹配,默认对英文支持较好,容错最多2个(和字符位置也有关系)
query=newFuzzyQuery(newTerm("content","daa"));
//4)数值范围
//参数分别:字段的名字,最小值,最大值,是否包含最小值边界,是否包含最大值边界
query=NumericRangeQuery.newLongRange("id", 102L, 103L, true, true);
//5)查询所有,忽略所有条件
query=newMatchAllDocsQuery();
//6)组合规则
// BooleanQuery booleanQuery = newBooleanQuery();
// Query query1 = new TermQuery(newTerm("content", keyword));
// Query query2 = new WildcardQuery(newTerm("content","*"+keyword+"*"));
// //参数1:查询的具体策略,参数2:组合策略
// booleanQuery.add(query1, Occur.MUST_NOT);
// booleanQuery.add(query2, Occur.MUST);
// //调用工具类
// LuceneUtils.printTopDocsByQuery(booleanQuery,Integer.MAX_VALUE);
LuceneUtils.printTopDocsByQuery(query, Integer.MAX_VALUE);
}
//修改
@Test
publicvoidtestUpdate() throwsException{
//1.创建Document文档(相当于一条数据)-是一篇文章
Document document=newDocument();
//在文档中加入Field字段
//1)业务编号:参数1:字段名字,参数2:字段值,参数3:是否存储
document.add(new LongField("id", 102, Store.YES));
//2)标题:TextField自动分词
document.add(new TextField("title", "如何做好人4",Store.YES));
//3)作者:StringField不分词
document.add(new StringField("author", "小七4",Store.YES));
//4)邮箱:只存储和显示,不能搜索
document.add(new StoredField("email", "[email protected]"));
//5)内容:
document.add(new TextField("content", "我是一个好人4,Goodman!", Store.YES));
IndexWriter indexWriter = LuceneUtils.getIndexWriter();
//参数1:要修改的词条的依据
//参数2:要修改后的文档
//bug:如果业务主键数据类型不是字符串,可能会出错,因此建议业务中主键存放到索引中的时候,都转成字符串
indexWriter.updateDocument(new Term("id", "102"),document);
}
//删除
//如果是用Term删除,要求ID也必须是字符串类型!
@Test
publicvoidtestDelete() throwsException{
IndexWriter indexWriter = LuceneUtils.getIndexWriter();
//1) 根据词条进行删除
// indexWriter.deleteDocuments(newTerm("id", "102"));
//2) 根据query对象删除,如果ID是数值类型,那么我们可以用数值范围查询锁定一个具体的ID
// Query query =NumericRangeQuery.newLongRange("id", 102L, 103L, true, true);
// indexWriter.deleteDocuments(query);
//3) 删除所有
indexWriter.deleteAll();
// // 提交
// indexWriter.commit();
}