Lucene索引库的维护
首先getIndexWriter
private IndexWriter getIndexWriter() throws Exception {
Directory directory = FSDirectory.open(new File("F:\\index"));
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
// 创建indexWriter
IndexWriter indexWriter = new IndexWriter(directory, config);
return indexWriter;
}
索引库的添加
@Test
// 索引库的添加
public void addDocument() throws Exception {
IndexWriter indexWriter = getIndexWriter();
// 创建document对象
Document document = new Document();
Field name = new TextField("name", "apache.txt", Store.YES);
name.setBoost(10.0f); // 设置相关度
document.add(name);
document.add(new TextField("name1", "我是name1", Store.YES));
document.add(new TextField("name2", "我是name2", Store.YES));
document.add(new LongField("content", 1000l, Store.NO));
// 添加document'到索引库
indexWriter.addDocument(document);
// 关闭
indexWriter.close();
}
索引库的删除
@Test
// 删除所有 注:慎用慎用!
public void deleteAllDocument() throws Exception {
IndexWriter indexWriter = getIndexWriter();
indexWriter.deleteAll();
indexWriter.commit();
indexWriter.close();
}
条件的删除
@Test
// 指定查询条件删除
public void deleteDocumentByQuery() throws Exception {
IndexWriter indexWriter = getIndexWriter();
// 创建查询条件
Query query = new TermQuery(new Term("name", "apache"));
indexWriter.deleteDocuments(query);
indexWriter.close();
}
索引库的修改
@Test
// 修改索引库 原理:先删除再添加
public void updateDocument() throws Exception {
IndexWriter indexWriter = getIndexWriter();
// 创建 document
Document document = new Document();
document.add(new TextField("name", "更新了的文档",Store.YES));
document.add(new TextField("content", "这个文档被更新了",Store.YES));
indexWriter.updateDocument(new Term("name", "apache"), document);
indexWriter.close();
}
Field域的属性
判断标准:是否要对域的内容进行分词。
2、是否索引:域中的内容是否要进行索引,如果不索引查询不到结果。
判断标准:是否要在域上进行查询。如果要查询就需要创建索引。
3、是否存储:是否把域的中的原始内容保存到磁盘。如果不存储域中是取不到结果的。
判断标准:是否要展示给用户看,或者业务逻辑中是否需要域的内容。
以此来进行field的子类的选择。( StringField、LongField、StoredField、TextField )
索引库的查询
对要搜索的信息创建Query对象,可通过两种方法创建查询对象。
首先抽取通用代码:
private IndexSearcher getIndexSearcher() throws Exception {
IndexReader indexReader = DirectoryReader.open(FSDirectory.open(new File("F:\\index")));
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
return indexSearcher;
}
private void printResult(Query query) throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
TopDocs topDocs = indexSearcher.search(query, 10);
System.out.println("查询的总记录数:" + topDocs.totalHits);
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
int id = scoreDoc.doc;
Document document = indexSearcher.doc(id);
// 取field的值
System.out.println("==============================================================================");
System.out.println(document.get("id"));
System.out.println(document.get("name"));
System.out.println("content:" + document.get("content"));
System.out.println(document.get("path"));
System.out.println(document.get("size"));
}
indexSearcher.getIndexReader().close();
}
1、使用lucene提供的Query子类
使用TermQuery进行查询:
@Test
// 创建TermQuery查询
public void testQueryTerm() throws Exception {
Query query = new TermQuery(new Term("name", "apache"));
System.out.println(query); // name:name
printResult(query);
}
查询所有:MatchAllDocsQuery
@Test
// 查询所有
public void testMatchAllDocsQuery() throws Exception {
Query query = new MatchAllDocsQuery();
System.out.println(query); // *:*
printResult(query);
}
根据数值范围查询:NumericRangeQuery
@Test
// 数值范围查询
public void testNumericRangeQuery() throws Exception {
Query query = NumericRangeQuery.newLongRange("size", 0l, 3000l, true, true);
System.out.println(query); // size:[0 TO 3000]
printResult(query);
}
@Test
// 多条件查询
public void testBooleanQuery() throws Exception {
BooleanQuery query = new BooleanQuery();
// 设置 条件
Query query1 = new TermQuery(new Term("name", "apache"));
Query query2 = NumericRangeQuery.newLongRange("size", 0l, 3000l, true, false);
// 组合
query.add(query1, Occur.MUST);
query.add(query2, Occur.MUST_NOT);
System.out.println(query); // +name:apache +size:[0 TO 3000}
printResult(query);
}
条件直接的关系:
Occur.MUST:条件必须满足,相当于AND
Occur.SHOULD:条件应该满足,相当于OR
Occur.MUST_NOT:条件必须不能满足,相当于NOT
Occur.SHOULD:条件应该满足,相当于OR
Occur.MUST_NOT:条件必须不能满足,相当于NOT
2、使用QueryParse解析查询表达式
先导入queryparser的jar包:在lucene目录下的扩展包中
@Test
// 分析查询时,默认域的查询
public void testQueryParser() throws Exception {
// 参数1: 默认搜索的域 参数2:分析器
QueryParser queryParser = new QueryParser("content", new IKAnalyzer());
Query query = queryParser.parse("Lucene is a apache project");
System.out.println(query); // content:lucene content:apache content:project is和a为停用词
printResult(query);
}
或
@Test
// 分析查询时,默认域的查询
public void testQueryParser() throws Exception {
// 参数1: 默认搜索的域 参数2:分析器
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
Query query = queryParser.parse("name:apache");
System.out.println(query);
printResult(query);
}
@Test
// 多个默认搜索域
public void testMulTiFieldQuery() throws Exception {
String[] fields = {"name","content"};
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
Query query = queryParser.parse("Lucene is a apache project");
System.out.println(query); // (name:lucene content:lucene) (name:apache content:apache) (name:project content:project)
printResult(query);
}
Lucene的查询语法:
1、基本语法:域名:关键字
如: name:apache
2、查询所有文档
*:*
3、范围查询语法:域名:[ 最小值 TO 最大值 ]
[ ]:包含边界值
{ }:不包含边界值
如:size:[ 0 TO 1000 ]
注:在lucene中范围查询只支持字符串类型,数值范围使用NumericRangeQuery。Solr中是支持的。
4、组合条件查询语法
+name:apache +size:[1000 TO 10000]+:相当于AND
name:apache size:[1000 TO 10000]没有前缀:相当于OR
-name:apache size:[1000 TO 10000]-:相当于NOT
第二种写法:
name:apache AND size:[1000 TO 10000]
name:apache OR size:[1000 TO 10000]
NOT name:apache size:[1000 TO 10000]
+name:apache +size:[1000 TO 10000]+:相当于AND
name:apache size:[1000 TO 10000]没有前缀:相当于OR
-name:apache size:[1000 TO 10000]-:相当于NOT
第二种写法:
name:apache AND size:[1000 TO 10000]
name:apache OR size:[1000 TO 10000]
NOT name:apache size:[1000 TO 10000]
相关度排序
相关度排序是查询结果按照查询关键字的相关性进行排序。越相关的越靠前。
相关度打分:
1、计算词的(term)的权重
2、根据权重值,采用空间向量模型算法计算文档相关度得分。
影响term权重的两个因素:
Term Frequency(tf):
指term在文档中出现了多少次。tf越大说明越重要。
Document Frequency(df):
指有多少文档包含此term。df越大说明越不重要。
设置boost影响得分结果:
@Test
// 索引库的添加
public void addDocument() throws Exception {
IndexWriter indexWriter = getIndexWriter();
// 创建document对象
Document document = new Document();
Field name = new TextField("name", "apache.txt", Store.YES);
name.setBoost(10.0f); // 设置相关度
document.add(name);
document.add(new TextField("name1", "我是name1", Store.YES));
document.add(new TextField("name2", "我是name2", Store.YES));
document.add(new LongField("content", 1000l, Store.NO));
// 添加document'到索引库
indexWriter.addDocument(document);
// 关闭
indexWriter.close();
}
Solr安装及配置
从官方网站下载Solr
Solr的安装步骤:
1、安装tomcat
2、把solr目录中dist下的war包部署到tomcat下,并改名为便于访问的solr.war。
2、把solr目录中dist下的war包部署到tomcat下,并改名为便于访问的solr.war。
3、启动tomcat以使solr.war包自动解压。再关闭tomcat后,删除war包。
4、把Solr目录下example\lib\ext目录下的jar包添加到solr工程中,日志相关。
5、配置磁盘索引库solrhome,solr服务器所有配置文件保存的目录。在example下的solr目录就是一个solrhome。
将这个目录复制到自定义的路径,并改名为solrhome。改名只是便于理解……
6、配置solr工程和solrhome之间的关系,告诉solr工程solrhome的位置:
4、把Solr目录下example\lib\ext目录下的jar包添加到solr工程中,日志相关。
5、配置磁盘索引库solrhome,solr服务器所有配置文件保存的目录。在example下的solr目录就是一个solrhome。
将这个目录复制到自定义的路径,并改名为solrhome。改名只是便于理解……
6、配置solr工程和solrhome之间的关系,告诉solr工程solrhome的位置:
修改solr工程的web.xml:解开注释,并修改value值。
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>D:\develop\solrhome</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
7、启动tomcat
Solr的后台管理界面
待续……