介绍

随着数据的快速增长,对数据的检索功能有了越来越高的要求,具体说就是要快,准,最早期涉及到全文检索技术的互联网企业只有搜索公司.对视频,图 片,文本信息,全部整理成索引文件,利用索引的特点(有序,结构,存储在磁盘,快速定位,文件)实现丰富查询功能的技术;

数据猛增,举例2014年数据
• youtube-一分钟上传400-500小时视频
• 苹果用户-每分钟下载51000应用
• 亚马逊-一分钟平均交易额22万美元
• Siri-一分钟回答错误10万个问题; • 谷歌:一分钟搜索词条次数亿次
需要准确度高,速度要快,数据量支持庞大的内容的技术实现搜索的单独处理-全文检索技术;

传统检索方式:内存检索,硬盘数据库检索

  • 内存检索:文档检索
    windows将打开的文档加载到内存,是在内存已经加载的内容中搜索; 快/准,数据量太小;
  • 硬盘数据库检索:
    利用索引的优化,对数据库创建海量表格处理不同类型数据,数量大/准,慢,无法应对多功能的搜索; like关键字没有使用索引;

检索系统结构

在一套检索系统中包含主题的三个部分:

  • 信息的原始采集:原始数据可以在数据库,也可以在日志,也可以在大数据存储分布式系统中,将原有数据获取保存
  • 信息的有效整理:原始数据非结构化,在采集系统中将原始数据进行分类整理(索引的创建),形成全文检索技术的索引文件
  • 信息的搜索系统:利用前端的系统(服务),给客户使用,从全文检索技术中获取客户端查询搜索的数据返回;

结构图(京东)

结构图[百度]

全文检索技术的应用位置:
○ 从原始数据整理成索引文件,需要全文检索技术
○ 从索引文件中保存的数据搜索,需要全文检索技术
围绕着索引文件运转的一种搜索技术

全文检索技术

倒排索引算法

全文检索技术中心,想要将有结构的非结构化的海量数据整理成可用的索引文件,需要一种算法完成,常见的就是倒排索引算法;

1.创建索引(百度网页)
原始数据多个网页:

网页1标题:看看美国怎么死
内容:中国与美国之间的贸易战到底会造成多少影响?
时间:2020/4/3
出版社:新华社
网页2
商品名称:三星固态硬盘
商品价钱:2000元
商品描述:最新产品,不受中美贸易战影响的全新商品
卖家信息:猫猫店铺
 网页3标题:美国要作死
内容:中国不惧美国挑衅
时间:2020/4/3
出版社:新华社

2.将原始数据封装成对应的全文检索对象(document)

document1(网页1)
title:看看美国怎么死
content:中国与美国之间的贸易战到底会造成多少影
响?
time:2020/4/3
publisher:新华社
document2(网页2)
product_name:三星固态硬盘
product_price:2000元
product_desc:最新产品,不受中美贸易战影响的全新商
品
shop_info:猫猫店铺
document3(网页3)
title:美国要作死
content:中国不惧美国挑衅
time:2020/4/3
publisher:新华社

在封装document时,根据业务需求的需要会从原始数据中剔除一些根本不可能会用来搜索的数据

  1. 将document进行数据的分词计算
    分词:原始数据,所有的字符串,根据分词的逻辑计算成最小意义的词语的过程–分词计算,例如:
 中国不惧美国挑衅--{中国},{不惧},{美国},{挑衅}
中华人民共和国--{中华},{中华人},{华人},{人民},{人民共和}

对于以上3个document计算的分词结果,会以分词结构存储下来

document1(id=1){title:{看看(1,出现频率,偏移量,位置等等)},{美国(1)},{怎么死(1)}
content:{中国(1)},{美国(1)},{贸易(1)},{影响(1)}
publisher:{新华社(1)}
}
ducument2(id=2){product_name:{三星(2)},{硬盘(2)}
product_price:{2000(2)},{2000元(2)}
shop_info:{猫猫(2)},{店铺(2)}
}
document3(id=3){title:{美国(3)},{作死(3)}
content:{中国(3)},{不惧(3)},{美国(3)},{挑衅(3)}
publisher:{新华社(1)}
}
  1. 分词的整合,整合索引的数据结构
    document1,2,3中有属性名称和分词结果完全一样的分词
美国([1,3],[title,content])
中国([1,3],[content])
新华社([1,3],[publisher])
三星([2],[product_name])
  1. 将分词结果输出到索引文件,将document数据输出到索引文件
  2. 搜索索引
    客户端传递的参数是"美国",可以利用全文检索创建的索引文件,从分词中立刻定位到"美国",([1,3],[title,content]),直接利用id定位到美国词出现在的所有document对象,返回List

    “中国与美国的贸易战”==分词逻辑的计算(可以做分页查询)
中国--一批document
美国--一批document
贸易--一批document
交集,并集,差集

lucene全文检索引擎包

介绍
创始人,Doug Cutting(狗哥),lucene的创始人,也是hadoop的创始人,lucene,开源的全文检索引擎工具包;极大的简化全文检索引擎的开发效率(源生创建语言java);

特点

  • 索引的数据速度150G/h(每小时可以从元数据中创建出索引文件的大小)
  • 对lucene运行时栈内存的使用1MB
  • 全量索引(第一次创建索引)速度和增量索引(数据的变化创建索引)类似;
  • 提供丰富的基于索引结构的搜索功能
词项查询(是所有查询的基础)
多域查询(多个属性title,content同时查询)
布尔查询(多个查询条件的逻辑关系结果)
范围查询(对数字特性的数据,价钱,点击量,内存大小,硬盘大小)
模糊查询(数据不确定时,使用的范围匹配)
通配查询

全文检索的概念

  • Query:搜索时,用来封装查询条件的对象,不同的查询功能,实现类是不一样,TermQuery,MultiFieldQuery,BooleanQuery;
  • document:文档对象,一个文档对象对应数据的一个基本单位:一个商品,一个用户,一个订单,一个物流单子,相当于一个数据库表格中的一行数据
  • field:域属性,每一个document中绑定使用的属性内容,根据原始数据定义这些域属性的值,或者类型.
  • Term:词项,分词计算的结果中每一个词语都可以成为全文检索中一个词项信息. 中华人民–{中华}{人民}

lucene中的分词计算

lucene中的分词:
全文检索中,分词重要性不言而喻,对于不同的语言环境,分词的逻辑也不同(英文文本和中文文本底层二进制编解码不一样,用中文分词逻辑分词英文,结果一定是错误的),lucene解决不同语言环境的分词逻辑;lucene提供了对外的分词器接口Analyzer;接口定义了实现规范;全球范围内的各种团队,是Analyzer实现接口就能完成各自需要的分词器逻辑;

SpringBoot整合lucene

利用自带的中文分词包
引入需要的各种依赖

 <dependencies><dependency> <!-- 查询相关jar包 --><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>6.0.0</version>
</dependency>
<dependency> <!-- lucene自带只能中文分词器jar包 --><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-smartcn</artifactId><version>6.0.0</version>
</dependency>
<dependency> <!-- 测试用到的lucene工具包 --><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>6.0.0</version>
</dependency>
<dependency> <!-- 测试用到的lucene核心包 --><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>6.0.0</version>
</dependency>

依赖中提供的各种lucene已经实现的分词器:

  • SmartChineseAnalyzer:智能中文分词器
  • WhitespaceAnalyzer:空格分词器
  • SimpleAnalzyer:简单分词器,以标点符号为分词一句
  • StandardAanalyzer:英文标准分
    测试代码
    编辑一个调用的方法,将不同的分词器实现对象和解析的字符串传递过来,通过Analyzer接口的相关各种方法api将解析结果打印输出
public void printAnalyzer(Analyzer analyzer,String str) throws Exception{//将字符串转化成字符串流StringReader reader=new StringReader(str);//将字符串流继续转化,转化成一个当前分词器底层计算结果的tocketStream//每一个分词过程,都要对应一个域属性,做分词计算TokenStream tokenStream = analyzer.tokenStream("test", reader);//tokenStream中流就已经是计算结果的二进制了tokenStream.reset();//从头,获取流数据中的字符串属性CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class);while(tokenStream.incrementToken()){//获取tokenStream中分词的所有词项结果System.out.println(attribute.toString());}}
@Testpublic void run() throws Exception{//创建几个分词器的实现类Analyzer a1=new SmartChineseAnalyzer();Analyzer a2=new WhitespaceAnalyzer();Analyzer a3=new SimpleAnalyzer();Analyzer a4=new StandardAnalyzer();Analyzer a5=new IKAnalyzer6x();//计算的字符串内容String msg="最新产品,不受中美贸易战影响的全新商品";System.out.println("**********智能中文分词器**************");printAnalyzer(a1, msg);System.out.println("**********空格分词器**************");printAnalyzer(a2, msg);System.out.println("**********简单分词器**************");printAnalyzer(a3, msg);System.out.println("**********标准分词器**************");printAnalyzer(a4, msg);

中文IK分词器
lucene中常用的一种中文分词器,对于Lucene6.0以上的版本暂时没
有对应版本的ik分词器,引入实现类

public class IKAnalyzer6x extends Analyzer{private boolean useSmart;public boolean useSmart(){return useSmart;}public void setUseSmart(boolean useSmart){this.useSmart=useSmart;}public IKAnalyzer6x(){this(false);//IK分词器lucene analyzer接口实现类,默认细粒度切分算法}//重写最新版本createComponents;重载analyzer接口,构造分词组件@Overrideprotected TokenStreamComponents createComponents(String filedName) {Tokenizer _IKTokenizer=new IKTokenizer6x(this.useSmart);return new TokenStreamComponents(_IKTokenizer);}public IKAnalyzer6x(boolean useSmart){super();this.useSmart=useSmart;}}
public class IKTokenizer6x extends Tokenizer{//ik分词器实现private IKSegmenter _IKImplement;//词元文本属性private final CharTermAttribute termAtt;//词元位移属性private final OffsetAttribute offsetAtt;//词元分类属性private final TypeAttribute typeAtt;//记录最后一个词元的结束位置private int endPosition;//构造函数,实现最新的Tokenizerpublic IKTokenizer6x(boolean useSmart){super();offsetAtt=addAttribute(OffsetAttribute.class);termAtt=addAttribute(CharTermAttribute.class);typeAtt=addAttribute(TypeAttribute.class);_IKImplement=new IKSegmenter(input, useSmart);}@Overridepublic final boolean incrementToken() throws IOException {//清除所有的词元属性clearAttributes();Lexeme nextLexeme=_IKImplement.next();if(nextLexeme!=null){//将lexeme转成attributestermAtt.append(nextLexeme.getLexemeText());termAtt.setLength(nextLexeme.getLength());offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());//记录分词的最后位置endPosition=nextLexeme.getEndPosition();typeAtt.setType(nextLexeme.getLexemeText());return true;//告知还有下个词元}return false;//告知词元输出完毕}@Overridepublic void reset() throws IOException {super.reset();_IKImplement.reset(input);}@Overridepublic final void end(){int finalOffset = correctOffset(this.endPosition);offsetAtt.setOffset(finalOffset, finalOffset);}}

将IKAnalyzer2012_u6.jar手动添加到工程

测试代码接上代码

@Testpublic void run() throws Exception{//创建几个分词器的实现类Analyzer a1=new SmartChineseAnalyzer();Analyzer a2=new WhitespaceAnalyzer();Analyzer a3=new SimpleAnalyzer();Analyzer a4=new StandardAnalyzer();Analyzer a5=new IKAnalyzer6x();//计算的字符串内容String msg="最新产品,不受中美贸易战影响的全新商品";System.out.println("**********智能中文分词器**************");printAnalyzer(a1, msg);System.out.println("**********IK中文分词器**************");printAnalyzer(a5, msg);/*System.out.println("**********空格分词器**************");printAnalyzer(a2, msg);System.out.println("**********简单分词器**************");printAnalyzer(a3, msg);System.out.println("**********标准分词器**************");printAnalyzer(a4, msg);*/}

但是无论如何更新,也无法赶上时代的步伐,总是有过时的和人为引入的分词
结果,无法达到系统对全文检索分词计算的要求如:王者荣耀–{王者} {荣耀}{王者荣耀},解决办法就是IK分词器扩展

Lucene创建索引和搜索索引数据

索引创建

public class CreateIndex {@Testpublic void createIndex() throws Exception{//1指定一个文件夹位置,项目根目录./index01Path path = Paths.get("d:/index01");//lucene的文件夹对象包装pathFSDirectory dir = FSDirectory.open(path);//2生成一个创建索引的输出对象//配置的生成,输出的原则覆盖,追加,输出计算分词的分词器IndexWriterConfig config=new IndexWriterConfig(new IKAnalyzer6x());//配置追加覆盖的原则 append create crate_or_appendconfig.setOpenMode(OpenMode.CREATE);IndexWriter writer=new IndexWriter(dir, config);//3编辑收集document数据的对象封装过程//添加一个新闻的数据,添加一个商品数据Document doc1=new Document();Document doc2=new Document();//封装数据手动封装,不同的field域属性和值doc1.add(new TextField("title", "文娱大播报1", Store.YES));//title,文旅部督办张云雷调侃事件doc1.add(new TextField("publisher","新华社1",Store.YES));doc1.add(new TextField("content","北京德云社火爆售票,每张票100元1",Store.NO));doc1.add(new TextField("name","三星屏幕1",Store.YES));doc1.add(new IntPoint("price", 500));doc1.add(new StringField("address","https://ent.deyunshe.com.cn",Store.YES));//网页数据的addresshttps://ent.sina.com.cndoc2.add(new TextField("title", "文娱大播报2", Store.YES));//title,文旅部督办张云雷调侃事件doc2.add(new TextField("publisher","新华社2",Store.YES));doc2.add(new TextField("content","北京德云社火爆售票,每张票100元2",Store.NO));doc2.add(new TextField("name","三星屏幕2",Store.YES));doc2.add(new IntPoint("price", 600));doc2.add(new StringField("address","https://ent.deyunshe.com.cn",Store.YES));//网页数据的addresshttps://ent.sina.com.cn/*doc2.add(new TextField("name","三星galaxy7",Store.YES));doc2.add(new StringField("price","222.22",Store.YES));doc2.add(new DoublePoint("price", 222.22));doc2.add(new StringField("image","http://image.jt.com/",Store.YES));*///Store.yes/no的区别,TextField和StringField区别//4利用输出writer写出索引文件,索引文件是空的writer.addDocument(doc1);/*writer.addDocument(doc2);*/writer.commit();}}

Field的常用类型
下边列出了开发中常用 的Filed类型,注意Field的属性,根据需求选择:

搜索索引的数据
lucene中提供丰富的查询功能,封装成查询对象Query的实例化类比如词项查询,封装TermQuery,多域查询,封装MultiFieldQuery就可以实现搜索输入流从index索引中获取查询结果的功能;

词项查询(TermQuery)
词项查询:提供一个词语,如果这个词语对应域名,存在一个分词的词项,那么就将词项对应的document返回给查询;

//词项查询:利用分词的结果对比,有就查询,没有就空@Testpublic void termQuery() throws Exception{//1指向索引文件Path path = Paths.get("d:/index01");FSDirectory dir = FSDirectory.open(path);//2 构造一个搜索对象,包装一个reader输入流IndexReader reader=DirectoryReader.open(dir);IndexSearcher search=new IndexSearcher(reader);//3 构造词项查询条件TermQuery//查询的对应域名称,和使用的词语,封装词项对象Term term=new Term("name","北京三星");//content nameQuery query=new TermQuery(term);//4查询获取结果集,从结果集中获取document的idTopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条//遍历获取id,通过id获取整整的数据对象document,观察每个document//对不不同查询条件的评分是不一样的;ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {//答应docuemnt的查询结果评分System.out.println("评分:"+scoreDoc.score);//从scoreDoc中获取document的idint id = scoreDoc.doc;//直接从数据中拿到document对象Document doc = search.doc(id);//根据存储数据是的各种类型定义,能够拿到数据结果System.out.println("title:"+doc.get("title"));System.out.println("content:"+doc.get("content"));System.out.println("publisher:"+doc.get("publisher"));System.out.println("name:"+doc.get("name"));System.out.println("price:"+doc.get("price"));System.out.println("address:"+doc.get("address"));System.out.println("image:"+doc.get("image"));}}

多域查询
根据指定的多个域进行查询,将查询条件进行分词的拆分例如,对content,name 查询"北京三星" 需要分词计算{北京}{三}{星} {三星},只要这些词项在2个域中存在任何一个,document就可以查到;

@Testpublic void multiFieldQuery() throws Exception{//指向index01FSDirectory dir = FSDirectory.open(Paths.get("d:/index01"));//查询对象searchIndexReader reader=DirectoryReader.open(dir);IndexSearcher search=new IndexSearcher(reader);//封装多域查询条件 Query query//定义多域的范围 content nameString[] fields={"content","name"};//需要构造一个多域的解析器,解析查询字符串成为多个词项Analyzer a=new IKAnalyzer6x();MultiFieldQueryParser parser=new MultiFieldQueryParser(fields,a);Query query=parser.parse("北京三星");//北京三星---{北京}{三}{星}{三星}//构造了8个TermQuery content 北京 三星 星 三,name 北京 三星 三 星//4查询获取结果集,从结果集中获取document的idTopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条//遍历获取id,通过id获取整整的数据对象document,观察每个document//对不不同查询条件的评分是不一样的;ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {//答应docuemnt的查询结果评分System.out.println("评分:"+scoreDoc.score);//从scoreDoc中获取document的idint id = scoreDoc.doc;//直接从数据中拿到document对象Document doc = search.doc(id);//根据存储数据是的各种类型定义,能够拿到数据结果System.out.println("title:"+doc.get("title"));System.out.println("content:"+doc.get("content"));System.out.println("publisher:"+doc.get("publisher"));System.out.println("name:"+doc.get("name"));System.out.println("price:"+doc.get("price"));System.out.println("address:"+doc.get("address"));System.out.println("image:"+doc.get("image"));}}

布尔查询
可以利用lucene多种查询条件查询结果集,也可以利用布尔查询条件将多个其他的查询条件作为子条件完成多个子条件间的结果集关系输出

@Testpublic void booleanQuery() throws Exception{//指向index01FSDirectory dir = FSDirectory.open(Paths.get("d:/index01"));//查询对象searchIndexReader reader=DirectoryReader.open(dir);IndexSearcher search=new IndexSearcher(reader);//需要多个子条件的查询对象TermQuery query1=new TermQuery(new Term("content","北京"));TermQuery query2=new TermQuery(new Term("name","三星"));//利用boolean查询的子条件封装query1query2BooleanClause bc1=new BooleanClause(query1,Occur.FILTER);BooleanClause bc2=new BooleanClause(query2,Occur.FILTER);//Occur 的常量 MUST MUST_NOT SHOULD  FILTER//SHOULD如何MUST在同一个布尔条件中,不会起作用//FILTER,MUST一个意思,但是结果中没有评分Query query=new BooleanQuery.Builder().add(bc1).add(bc2).build();//4查询获取结果集,从结果集中获取document的idTopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条//遍历获取id,通过id获取整整的数据对象document,观察每个document//对不不同查询条件的评分是不一样的;ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {//答应docuemnt的查询结果评分System.out.println("评分:"+scoreDoc.score);//从scoreDoc中获取document的idint id = scoreDoc.doc;//直接从数据中拿到document对象Document doc = search.doc(id);//根据存储数据是的各种类型定义,能够拿到数据结果System.out.println("title:"+doc.get("title"));System.out.println("content:"+doc.get("content"));System.out.println("publisher:"+doc.get("publisher"));System.out.println("name:"+doc.get("name"));System.out.println("price:"+doc.get("price"));System.out.println("address:"+doc.get("address"));System.out.println("image:"+doc.get("image"));}}

范围查询
指定查询的域必须存在Point类型的特点,根据上限和下限值的设置可以查询对应数据的范围结果,从而获取document数据;//根据数据中的数字特性类型IntPoint,调用方法获取范围查询的条件
Query query = IntPoint.newRangeQuery(“price”, 450, 550);
模糊查询
对于英文人名查询,tramp,没有清晰的查询条件,可以利用模糊查询lucene对字符串有模糊计算,可以利用trump查到tramp tromp 等 FuzzQuery query=new FuzzyQuery(new Term(“person_name”,“trump”))
中文:曰,日,灵,炅
通配符查询(?)
有时候需要从词项中,找到对应通配的逻辑,{三星},{三天},{三个}可以利用通配查询{三?}代替后面字符串
WildcardQuery query=new WildcardQuery(new
Term(“name”,“三?”))

@Testpublic void rangeQuery() throws Exception{//指向index01FSDirectory dir = FSDirectory.open(Paths.get("d:/index01"));//查询对象searchIndexReader reader=DirectoryReader.open(dir);IndexSearcher search=new IndexSearcher(reader);//根据数据中的数字特性类型IntPoint,调用方法获取范围查询的条件Query query = IntPoint.newRangeQuery("price", 450, 550);//4查询获取结果集,从结果集中获取document的idTopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条//遍历获取id,通过id获取整整的数据对象document,观察每个document//对不不同查询条件的评分是不一样的;ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {//答应docuemnt的查询结果评分System.out.println("评分:"+scoreDoc.score);//从scoreDoc中获取document的idint id = scoreDoc.doc;//直接从数据中拿到document对象Document doc = search.doc(id);//根据存储数据是的各种类型定义,能够拿到数据结果System.out.println("title:"+doc.get("title"));System.out.println("content:"+doc.get("content"));System.out.println("publisher:"+doc.get("publisher"));System.out.println("name:"+doc.get("name"));System.out.println("price:"+doc.get("price"));System.out.println("address:"+doc.get("address"));System.out.println("image:"+doc.get("image"));}}

全文检索第一篇lucene的使用相关推荐

  1. SpringBoot+Lucene第一篇——引出Lucene

    Lucene的学习第一篇--引出Lucene 一:需求场景提出: 1:在指定(10个)不同名字,不同内容的word文档中,进行任意指定搜索. 比如:搜索哪个文档中有:"高富帅",& ...

  2. Lucene第一篇【介绍Lucene、快速入门】

    tags: Lucene 什么是Lucene?? Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的 ...

  3. b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释

    b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释 继续上篇,上篇里忘记了也很重要的前端部分,今天的网站基本上是以一个启示页,然后少量的整页切换,大量的浏览器后台调用web服务局部.动态更 ...

  4. 【手把手教你全文检索】Apache Lucene初探

    讲解之前,先来分享一些资料 首先呢,学习任何一门新的亦或是旧的开源技术,百度其中一二是最简单的办法,先了解其中的大概,思想等等.这里就贡献一个讲解很到位的ppt.已经被我转成了PDF,便于搜藏. 其次 ...

  5. ElasticSearch入门 第一篇:Windows下安装ElasticSearch

    这是ElasticSearch 2.4 版本系列的第一篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  6. 2020年我的第一篇博客日报

    博客日报缘由 谈起博客我们常想到CSDN.博客园.github等 谈起日报.周报我们自然想到了,工作工作工作... 但是谈起博客日报,那又是什么呢? "博客日报"不知道有没有这个词 ...

  7. 聊聊后端程序员的知识体系-第一篇

    聊聊后端程序员的知识体系-第一篇 原文链接:https://www.fpthinker.com/backend_knowledge_architecture/knowledge.htmll 亲爱的读者 ...

  8. 【全文检索_03】Lucene 基本使用

    1.1 分词器 1.1.1 默认分词器   在上一文 [全文检索_02]Lucene 入门案例 中我们使用 Lucene 默认分词器对中文版双城记进行分词,这个操作其实是有问题的.哎?!我们明明分词成 ...

  9. 属于窄带噪声的是热噪声_时钟201系列: 非相位噪声的情况 (第一篇)

    欢迎来到Silicon Labs(亦称"芯科科技")的新系列博客文章"时钟201"的第一篇内容-非相位噪声的情况-第一部分.我们之前的系列博文"时钟1 ...

最新文章

  1. KDE与GNOME的起源与发展
  2. OpenGL indexedCube索引多维数据集的实例
  3. 形容PHP程序员的语句,形容程序员的句子
  4. Java消息队列总结只需一篇解决ActiveMQ、RabbitMQ、ZeroMQ、Kafka
  5. yytextview 复制_用YYTextView 实现填空题作答功能
  6. mysql sql dateadd_在SQL语句中DATEADD和DATEDIFF函数
  7. FFmpeg总结(十)用ffmpeg进行在视频中加水印图、加gif图
  8. 将Nginx添加到系统服务
  9. unity 2018.3.0版本界面汉化
  10. vue结合vue-amap调用高德地图行政区划分
  11. c语言的矩阵相乘程序,C语言实现两个矩阵相乘
  12. linux设置开机自启动命令
  13. C语言刷题训练营-第一讲
  14. ubuntu 16.04 gtx1060 显卡安装
  15. Unity-解决报错Shader error in ‘EffectCore/alphaBlend_glow‘: ‘‘ : ‘UNITY_PASS_FORWARDBASE‘ already define
  16. 学历学籍系统-Web服务开发实验(REST API)
  17. idea快速搭建ssm框架
  18. Oracle数据库11gR2完全干净卸载 - deinstall
  19. SAP重置公司代码资产会计(FI-AA)数据-OABL
  20. python接口测试+ununittest之verbosity

热门文章

  1. bzoj4605: 崂山白花蛇草水 权值线段树套KDtree
  2. 计算机英语名词简释(轉載)
  3. QQ局域网聊天软件MFC CSocket编程
  4. t440p安装黑苹果+win10双系统记录
  5. matlab使用教训
  6. HBuilderX 终端显示空白问题
  7. Windows 缺失msvcp140.dll文件
  8. python入门系列:包和模块
  9. CGO arm 树莓pi下的交叉编译
  10. UOS系统怎么进入开发者模式教程