A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© buluo 初级黑马   /  2018-3-18 10:17  /  1711 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

1.数据1.1数据分类
  • 结构化数据
    • 指具有固定格式或有限长度的数据,如数据库,元数据等。
  • 非结构化数据
    • 不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件

1.2非数据结构化数据查询方法
(1) 顺序扫描法(Serial Scanning)
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。
(2)全文检索(Full-text Search)
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
1.3如何实现全文检索
可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
1.4全文检索的应用场景
对于数据量大、数据结构不固定的数据可采用全文检索方式搜索,比如百度、Google等搜索引擎、论坛站内搜索、电商网站站内搜索等。
2Lucene
file:///C:/Users/dell/Documents/My%20Knowledge/temp/b5b03bc9-3ecd-439b-874d-56aedeaf69cb/128/index_files/wps68DD.tmp43f51ef4-af82-4669-b8cb-abddc005a89b.jpg
2.1Lucene简介Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆.2.2创建索引库
1.创建一个java工程导入jar包
2.创建一个indexwriter对象
1)指定索引库的存放位置Directory对象
2)指定一个分析器,对文档内容进行分析。
3.创建document对象
4.创建field对象,将field添加到document对象中
5.使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
6.关闭IndexWriter对象。
注意:
* 获取文档:采集数据
* 如果我们数据来自数据库:jdbc
* 数据来自文件系统:IO流
* 数据来自网络:可以发送http请求框架或者jar包,jsoup,httpClient,natch
2.3Filed域的属性2.3.1 Field域的三个属性
1.是否分词:是否对域的内容进行分词处理。前提是我们要对域的内容进行查询。
2.是否索引:将Field分析后的词或整个Field值进行索引,只有索引方可搜索到。
比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。
3.是否存储:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取
比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。
file:///C:/Users/dell/Documents/My%20Knowledge/temp/b5b03bc9-3ecd-439b-874d-56aedeaf69cb/128/index_files/40a6f3f4-69fb-45ca-92ac-a5182a386528.png
file:///C:/Users/dell/Documents/My%20Knowledge/temp/b5b03bc9-3ecd-439b-874d-56aedeaf69cb/128/index_files/3dfb819e-62eb-4417-8684-7fb943bb668b.png
案例
//创建索引
@Test
public void createIndex() throws Exception {
//指定索引库存放的路径
//D:\temp\0108\index
Directory directory = FSDirectory.open(new File("D:\\temp\\0108\\index"));
//索引库还可以存放到内存中
//Directory directory = new RAMDirectory();
//创建一个标准分析器
Analyzer analyzer = new StandardAnalyzer();
//创建indexwriterCofig对象
//第一个参数: Lucene的版本信息,可以选择对应的lucene版本也可以使用LATEST
//第二根参数:分析器对象
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
//创建indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, config);
//原始文档的路径D:\传智播客\01.课程\04.lucene\01.参考资料\searchsource
File dir = new File("D:\\传智播客\\01.课程\\04.lucene\\01.参考资料\\searchsource");
for (File f : dir.listFiles()) {
//文件名
String fileName = f.getName();
//文件内容
String fileContent = FileUtils.readFileToString(f);
//文件路径
String filePath = f.getPath();
//文件的大小
long fileSize  = FileUtils.sizeOf(f);
//创建文件名域
//第一个参数:域的名称
//第二个参数:域的内容
//第三个参数:是否存储
Field fileNameField = new TextField("filename", fileName, Store.YES);
//文件内容域
Field fileContentField = new TextField("content", fileContent, Store.YES);
//文件路径域(不分析、不索引、只存储)
Field filePathField = new StoredField("path", filePath);
//文件大小域
Field fileSizeField = new LongField("size", fileSize, Store.YES);
//创建document对象
Document document = new Document();
document.add(fileNameField);
document.add(fileContentField);
document.add(filePathField);
document.add(fileSizeField);
//创建索引,并写入索引库
indexWriter.addDocument(document);
}
//关闭indexwriter
indexWriter.close();
}



2.4使用Luke工具查看索引文件
file:///C:/Users/dell/Documents/My%20Knowledge/temp/b5b03bc9-3ecd-439b-874d-56aedeaf69cb/128/index_files/1c299179-8e07-46d8-b766-e05169938621.png
2.5查询索引2.5.1 实现步骤
第一步:创建一个Directory对象,也就是索引库存放的位置。
第二步:创建一个indexReader对象,需要指定Directory对象。
第三步:创建一个indexsearcher对象,需要指定IndexReader对象
第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
第五步:执行查询。
第六步:返回查询结果。遍历查询结果并输出。
第七步:关闭IndexReader对象
2.5.2 IndexSearcher搜索方法
方法
说明
indexSearcher.search(query, n)
根据Query搜索,返回评分最高的n条记录
indexSearcher.search(query, filter, n)
根据Query搜索,添加过滤策略,返回评分最高的n条记录
indexSearcher.search(query, n, sort)
根据Query搜索,添加排序策略,返回评分最高的n条记录
indexSearcher.search(booleanQuery, filter, n, sort)
根据Query搜索,添加过滤策略,添加排序策略,返回评分最高的n条记录



2.5.3代码实现
//查询索引库
@Test
public void searchIndex() throws Exception {
//指定索引库存放的路径
//D:\temp\0108\index
Directory directory = FSDirectory.open(new File("D:\\temp\\0108\\index"));
//创建indexReader对象
IndexReader indexReader = DirectoryReader.open(directory);
//创建indexsearcher对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//创建查询
Query query = new TermQuery(new Term("filename", "apache"));
//执行查询
//第一个参数是查询对象,第二个参数是查询结果返回的最大值
TopDocs topDocs = indexSearcher.search(query, 10);
//查询结果的总条数
System.out.println("查询结果的总条数:"+ topDocs.totalHits);
//遍历查询结果
//topDocs.scoreDocs存储了document对象的id
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
//scoreDoc.doc属性就是document对象的id
//根据document的id找到document对象
Document document = indexSearcher.doc(scoreDoc.doc);
System.out.println(document.get("filename"));
//System.out.println(document.get("content"));
System.out.println(document.get("path"));
System.out.println(document.get("size"));
}
//关闭indexreader对象
indexReader.close();
}



2.5.4TopDocs
Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性
方法或属性
说明
totalHits
匹配搜索条件的总记录数
scoreDocs
顶部匹配记录


注意:
Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)
TopDocs.totalHits:是匹配索引库中所有记录的数量
TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n
2.6支持中文分词器2.6.1分析器(Analyzer)的执行流程
file:///C:/Users/dell/AppData/Local/Temp/ksohtml/wps52E6.tmpcf49fe03-651f-4342-a32f-20d69e52325a.jpg
从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Token。
要看分析器的分析效果,只需要看Tokenstream中的内容就可以了。每个分析器都有一个方法tokenStream,返回一个tokenStream对象。
2.6.2分析器的分词代码
//查看标准分析器的分词效果
public void testTokenStream() throws Exception {
//创建一个标准分析器对象
Analyzer analyzer = new StandardAnalyzer();
//获得tokenStream对象
//第一个参数:域名,可以随便给一个
//第二个参数:要分析的文本内容
TokenStream tokenStream = analyzer.tokenStream("test", "The Spring Framework provides a comprehensive programming and configuration model.");
//添加一个引用,可以获得每个关键词
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();
}



2.6.3Lucene自带中文分词器
l StandardAnalyzer:
单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
效果:“我”、“爱”、“中”、“国”。
l CJKAnalyzer
二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。
上边两个分词器无法满足需求。
l SmartChineseAnalyzer
对中文支持较好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理
2.6.4第三方中文分析器
· paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代码在 2008-06-03,在svn中最新也是2010年提交,已经过时,不予考虑。
· mmseg4j:最新版已从 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代码是2014年6月,从09年~14年一共有:18个版本,也就是一年几乎有3个大小版本,有较大的活跃度,用了mmseg算法。
· IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。
· ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags仅有1.1版本,从2012年到2014年更新了大小6次,但是作者本人在2014年10月10日说明:“可能我以后没有精力来维护ansj_seg了”,现在由”nlp_china”管理。2014年11月有更新。并未说明是否支持Lucene,是一个由CRF(条件随机场)算法所做的分词算法。
· imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/ , 最新更新也在2009年5月,下载源码,不支持Lucene 4.10 。是利用HMM(隐马尔科夫链)算法。
· Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,作者有较高的活跃度。利用mmseg算法。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马