全文检索之lucene的使用(上)

本文介绍Lucene全文检索技术的基础使用方法,包括如何建立索引、搜索索引、管理索引(如增删改查),并提供了多种查询方式的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

全文检索技术适合做各种网站的站内搜索,例如京东,淘宝等电商网站,是一门非常使用的技术,这里讲解其原生技术lucene的使用,在全文检索之lucene的使用(下)讲讲解框架solr的使用,lucene的jar下载地址:http://lucene.apache.org/
以下为代码实现:
package com.ilike.lucene;

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
* 全文检索引擎lucene的使用 ①导入相应的jar包及配置文件包括如下 :
* commons-io-2.4.jar
* IKAnalyzer2012FF_u1.jar
* lucene-analyzers-common-4.10.3.jar
* lucene-analyzers-smartcn-4.10.3.jar
* lucene-core-4.10.3.jar
* lucene-queryparser-4.10.3.jar
*
* IKAnalyzer.cfg.xml
* ext.dic(需要识别的新词)
* stopword.dic(不需要创建索引的词)
*
* @author 桑伟东
*
*/

public class LuceneDemo1 {

/*
 * 1.创建索引
 */
@Test
public void testCreateIndex1() throws Exception {
    // 1.1 创建一个indexWriter对象
    Directory directory = FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));
    // Analyzer analyzer=new
    // StandardAnalyzer();//该分析器是apache官方推介使用,但是只适合分析英文
    Analyzer analyzer = new IKAnalyzer();// 这是一个较为强大的中文分析器
    IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, analyzer);
    IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
    // 1.2创建field对象,将field添加到document对象中
    // 加载你要创建索引的文件
    File file = new File("D:\\tmp\\lucene_temp_src");
    File[] files = file.listFiles();
    for (File file2 : files) {
        // 1.3创建document对象
        Document document = new Document();
        // 1.3.1文件名称
        String file_name = file2.getName();
        Field fileNameField = new TextField("fileName", file_name, Store.YES);// YES表示存储在索引库中,反之则不存
        // 1.3.2文件大小
        Long file_size = FileUtils.sizeOf(file2);
        Field fileSizeField = new LongField("fileSize", file_size, Store.YES);
        // 1.3.3文件路径
        String file_path = file2.getPath();
        Field filePathField = new StoredField("filePath", file_path);
        // 1.3.4文件内容
        String file_content = FileUtils.readFileToString(file2);
        Field fileContentField = new TextField("fileContent", file_content, Store.NO);
        // 1.3.5将域对象添加到document中
        document.add(fileNameField);
        document.add(fileSizeField);
        document.add(filePathField);
        document.add(fileContentField);
        // 1.4使用indexWriter对象将document对象写入文档库
        indexWriter.addDocument(document);
    }
    // 1.5关闭indexWriter对象
    indexWriter.close();
}

/*
 * 2.搜索索引
 */
@Test
public void testSearchIndex1() throws Exception {
    // 2.1创建Directory对象,也就是索引库的位置
    Directory directory = FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));
    // 2.2创建indexReader对象,需要制定Directory
    IndexReader indexReader = DirectoryReader.open(directory);
    // 2.3创建indexSearch对象,需要制定IndexReader
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    // 2.4创建一个TearmQuery对象,指定查询的域和查询的关键词
    Query query = new TermQuery(new Term("fileN", "文件名"));
    // 2.5执行查询
    TopDocs topDocs = indexSearcher.search(query, 10);
    // 2.6返回查询结果,遍历查询结果并输出
    ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    for (ScoreDoc scoreDoc : scoreDocs) {
        int docId = scoreDoc.doc;
        Document document = indexSearcher.doc(docId);
        // 文件名称
        String file_name = document.get("fileName");
        System.out.println(file_name);
        // 文件内容
        String file_content = document.get("fileContent");
        System.out.println(file_content);
        // 文件大小
        String file_size = document.get("fileSize");
        System.out.println(file_size);
        // 文件路径
        String file_path = document.get("filePath");
        System.out.println(file_path);
        System.out.println("---------------------");
    }
    // 2.7关闭indexReader对象
    indexReader.close();
}

/**
 * 可以挑选不同的分析器查看不同的分词效果,IKAnalyzer分词器目前最适合分析中文 如果有新词出现,可添加到配置文件ext.dic中
 * 
 * @throws Exception
 */
@Test
public void testTokenStream() throws Exception {
    // 创建一个标准分析器对象
    // Analyzer analyzer = new StandardAnalyzer();
    // Analyzer analyzer = new CJKAnalyzer();
    // Analyzer analyzer = new SmartChineseAnalyzer();
    Analyzer analyzer = new IKAnalyzer();
    // 获得tokenStream对象
    // 第一个参数:域名,可以随便给一个
    // 第二个参数:要分析的文本内容
    // TokenStream tokenStream = analyzer.tokenStream("test",
    // "The Spring Framework provides a comprehensive programming and
    // configuration model.");
    TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据");
    // 添加一个引用,可以获得每个关键词
    CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
    // 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
    OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
    // 将指针调整到列表的头部
    tokenStream.reset();
    // 遍历关键词列表,通过incrementToken方法判断列表是否结束
    while (tokenStream.incrementToken()) {
        // 关键词的起始位置
        System.out.println("start->" + offsetAttribute.startOffset());
        // 取关键词
        System.out.println(charTermAttribute);
        // 结束位置
        System.out.println("end->" + offsetAttribute.endOffset());
    }
    tokenStream.close();
}

}

package com.ilike.lucene;

import java.io.File;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
* 索引管理(增加,修改,删除,查询)
* 增加:入门程序类LuceneDemo1已写过
* 修改:
* 删除:
* 查询:入门程序类LuceneDemo1已写过精准查询
* 查询方式:①子类查询:只需要按照查询需求,挑选Query的子类即可
* ②解析查询:需要写语法,可打印子类查询中的query对象,了解语法
* @author 桑伟东
*
*
*/

public class LuceneManager {

/*1.删除全部索引
 * 
 */
@Test
public void testDeleteAll() throws Exception {
    // 1.1获取indexWriter对象
    IndexWriter indexWriter=getIndexWriter();
    // 1.2调用方法删除所有索引
    indexWriter.deleteAll();
    // 1.3关闭流
    indexWriter.close();
}
/**
 * 2.根据条件删除指定索引
 * @throws Exception
 */
@Test
public void testDeleteByCondition() throws Exception {
    // 2.1获取indexWriter对象
    IndexWriter indexWriter=getIndexWriter();
    // 2.2创建查询条件(fileName中名字中带有apache的索引)
    Query query=new TermQuery(new Term("fileName", "apache"));
    // 2.3调用方法删除指定索引
    indexWriter.deleteDocuments(query);
    // 2.4关闭流
    indexWriter.close();
}

/**
 * 3.修改索引的方法
 * @throws Exception
 */
@Test
public void testUpdateByCondition() throws Exception {
    // 3.1获取indexWriter对象
    IndexWriter indexWriter=getIndexWriter();
    // 3.2创建要新增的索引
    Document document=new Document();
    document.add(new TextField("fileN", "测试文件名1", Store.YES));
    document.add(new TextField("fileC", "测试文件1的内容", Store.YES));
    // 3.3调用方法修改指定的索引(第一个参数中的内容会被删除,第二个参数是要新增的内容,第三个参数是中文词法分析器对象)
    indexWriter.updateDocument(new Term("fileName", "apache"), document, new IKAnalyzer());
    // 3.4关闭流
    indexWriter.close();
}
/**
 * 4.查询所有
 * @throws Exception
 */
@Test
public void testQueryAll() throws Exception {
    // 4.1获取IndexSearcher对象
    IndexSearcher indexSearcher=getIndexSearcher();
    // 4.2创建一个MatchAllDocsQuery对象
    Query query=new MatchAllDocsQuery();
    // 4.3执行查询并打印查询结果
    printQueryResult( query, indexSearcher);
    // 4.4关闭资源
    indexSearcher.getIndexReader().close();

}

/**
 * 5.根据数值范围查询
 * @throws Exception
 */
@Test
public void testQueryByCondition() throws Exception {
    // 5.1获取IndexSearcher对象
    IndexSearcher indexSearcher=getIndexSearcher();
    // 5.2创建一个NumericRangeQuery对象,("fileSize"表示域,
       //20l表示最小值,1000l表示最大值,false表示不包含20,true表示包含1000
    Query query=NumericRangeQuery.newLongRange("fileSize", 20l, 1000l, false, true);
    // 5.3执行查询并打印查询结果
    printQueryResult( query, indexSearcher);
    // 5.4关闭资源
    indexSearcher.getIndexReader().close();

}

/**
 * 6.多条件组合查询
 * @throws Exception
 */
@Test
public void testQueryByConditions() throws Exception {
    // 5.1获取IndexSearcher对象
    IndexSearcher indexSearcher=getIndexSearcher();
    // 5.2创建组合查询的条件
    BooleanQuery booleanQuery=new BooleanQuery();
    Query query1=new TermQuery(new Term("fileName", "java"));
    Query query2=NumericRangeQuery.newLongRange("fileSize", 10l, 100000l, false, true);
    // 5.3执行查询并打印查询结果(MUST表示条件必须满足,MUST_NOT表示不满足,SHOULD表示可以没有)
    booleanQuery.add(query1, Occur.MUST);
    booleanQuery.add(query2, Occur.MUST);
    printQueryResult( booleanQuery, indexSearcher);
    // 5.4关闭资源
    indexSearcher.getIndexReader().close();

}


/**
 * 1.条件解析的对象查询
 * @throws Exception 
 */
@Test
public void testParserQuery() throws Exception {
    // 1.1获取IndexSearcher对象
    IndexSearcher indexSearcher=getIndexSearcher();
    // 1.2创建查询的条件,默认查询的域是fileName
    QueryParser queryParser=new QueryParser("fileName", new IKAnalyzer());
    //Query query=queryParser.parse("*:*");// *:*代表     域:值,写法可以参照上文的查询,打印上文查询中的query对象就可知道
    Query query=queryParser.parse("apache");//表示查询默认fileName域的apache
    printQueryResult( query, indexSearcher);
    // 1.4关闭资源
    indexSearcher.getIndexReader().close();


}


/**
 * 2.条件解析的对象查询(多个默认查询域)
 * @throws Exception 
 */
@Test
public void testParserQuery2() throws Exception {
    // 1.1获取IndexSearcher对象
    IndexSearcher indexSearcher=getIndexSearcher();
    // 1.2创建查询的条件,默认查询的域是fileName和fileContent
    String [] fields={"fileName","fileContent"};
    MultiFieldQueryParser multiFieldQueryParser=new MultiFieldQueryParser(fields, new IKAnalyzer());

    //Query query=queryParser.parse("*:*");// *:*代表     域:值
    Query query=multiFieldQueryParser.parse("apache is java");//表示查询默认fileName域的apache
    printQueryResult( query, indexSearcher);
    // 1.4关闭资源
    indexSearcher.getIndexReader().close();


}





/**
 * 抽取获得IndexWriter的方法
 * @return
 * @throws Exception
 */
private IndexWriter getIndexWriter() throws Exception {
    // 1.1 创建一个indexWriter对象
    Directory directory =FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));
    Analyzer  analyzer=new StandardAnalyzer();
    IndexWriterConfig indexWriterConfig=new IndexWriterConfig(Version.LATEST, analyzer);
    return new IndexWriter(directory, indexWriterConfig);
}




/**
 * 抽取获得IndexSearcher的方法
 * @return
 * @throws Exception
 */
private IndexSearcher getIndexSearcher() throws Exception {
    // 2.1创建Directory对象,也就是索引库的位置
    Directory directory =FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));
    // 2.2创建indexReader对象,需要制定Directory
    IndexReader indexReader=DirectoryReader.open(directory);
    // 2.3创建indexSearch对象,需要制定IndexReader
    return new IndexSearcher(indexReader);
}


private void printQueryResult(Query query,IndexSearcher indexSearcher) throws Exception {
    // 2.5执行查询
            TopDocs  topDocs =indexSearcher.search(query, 10);
            // 2.6返回查询结果,遍历查询结果并输出
            ScoreDoc [] scoreDocs=  topDocs.scoreDocs;
             for (ScoreDoc scoreDoc : scoreDocs) {
                  int docId=scoreDoc.doc;
                Document document=indexSearcher.doc(docId);
                //文件名称
                String file_name1=document.get("fileName");
                System.out.println(file_name1);
                //文件内容
                String file_content1=document.get("fileC");
                System.out.println(file_content1);
                //文件大小
                String  file_size=document.get("fileSize");
                System.out.println(file_size);
                //文件路径
                String file_path=document.get("filePath");
                System.out.println(file_path);
                System.out.println("---------------------");
             }
}

}

配置文件内容如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值