保持数据库与索引库的同步
说明:在一个系统中,如果索引功能存在,那么数据库和索引库应该是同时存在的。这个时候需要保证索引库的数据和数据库中的数据保持一致性。可以在对数据库进行增、删、改操作的同时对索引库也进行相应的操作。这样就可以保证数据库与索引库的一致性。
工具类DocumentUtils
说明:在对索引库进行操作时,增、删、改过程要把一个JavaBean封装成Document,而查询的过程是要把一个Document转化成JavaBean。在进行维护的工作中,要反复进行这样的操作,所以我们有必要建立一个工具类来重用代码。
public class DocumentUtils {
public static Document article2Document(Article article){
Document document = new Document();
Field idField = new Field("id",article.getId().toString(),Store.YES,Index.NOT_ANALYZED);
Field titleField = new Field("title",article.getTitle(),Store.YES,Index.ANALYZED);
Field contentField = new Field("content",article.getContent(),Store.YES,Index.ANALYZED);
document.add(idField);
document.add(titleField);
document.add(contentField);
return document;
}
public static Article document2Article(Document document){
Article article = new Article();
article.setId(Long.parseLong(document.get("id")));
article.setTitle(document.get("title"));
article.setContent(document.get("content"));
return article;
}
}
什么情况下使用Index.NOT_ANALYZED
当这个属性的值代表的是一个不可分割的整体,例如 ID
什么情况下使用Index.ANALYZED
当这个属性的值代表的是一个可分割的整体
LuceneUtils
LuceneUtils 这个类把Directory和Analyzer进行了包装。因为在创建IndexWriter时,需要用到这两个类,而管理索引库的操作都要用到IndexWriter这个类,所以我们对Directory和Analyzer进行了包装
public class LuceneUtils {
public static Directory directory;
public static Analyzer analyzer;
static{
try{
directory = FSDirectory.open(new File("./indexDir"));
analyzer = new StandardAnalyzer(Version.LUCENE_30);
}catch(Exception e){
e.printStackTrace();
}
}
}
管理索引库
增加索引库
@Test
public void testSaveIndex(){
//创建一个article对象,并且把信息存放进去
Article article = new Article();
article.setId(1L);
article.setTitle("lucene可以做搜索引擎");
article.setContent("baidu,goole都是很好的搜索引擎");
IndexWriter indexWriter = null;
try {
indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
Document doc = DocumentUtils.article2Document(article);
indexWriter.addDocument(doc);
indexWriter.commit();
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
indexWriter.close();
} catch (CorruptIndexException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
说明:在程序的最后必须在finally中写关闭资源的操作。因为这里有IO流的读写操作。
删除索引库
/**
* 一般情况下索引库的删除用关键词
* @throws Exception
*/
@Test
public void testDeleteIndex() throws Exception{
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
//indexWriter.deleteAll()删除所有的索引值
/**
* term就为关键词对象
*/
Term term = new Term("title", "lucene");
indexWriter.deleteDocuments(term);
indexWriter.close();
}
删除前:
删除后:
说明:indexWriter.deleteDocuments的参数为Term.Term指关键词。因为ID的索引保存类型为Index.NOT_ANALYZED,因为直接写ID即可。
修改索引库
/**
* 修改
* 先删除后增加
*/
@Test
public void testUpdateIndex() throws Exception{
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
Term term = new Term("title", "lucene");
Article article = new Article();
article.setId(1L);
article.setTitle("lucene可以做搜索引擎");
article.setContent("修改后的内容");
/**
* term是用删除的
* document是用于增加的
*/
indexWriter.updateDocument(term, DocumentUtils.article2Document(article));
indexWriter.close();
}
删除索引库重新创建索引库:
修改索引库:
说明:lucene的更新操作与数据库的更新操作是不一样的。因为在更新的时候,有可能变换了关键字的位置,这样分词器对关键字还得重新查找,而且还得在目录和内容中替换,这样做的效率比较低,所以lucene的更新操作是删除和增加两步骤来完成的。