全文索引的索引创建关键步骤是分词 。
文章1:马蓉带着俩孩子快乐玩耍王宝强面容憔悴;
文章2:王宝强另结新欢熊乃瑾却想念孩子;
分词第一步:
文章1;(马蓉,文章1,出现次数1),(带着,1,1),(孩子,1,1),
(王宝强,1,1);
文章2;(王宝强,2,1),(新欢,2,1),(另结新欢,2,1),
(熊乃瑾,2,1),(孩子,2,1);
(疑难杂症,2,1)
有重复出现在多个文章的词;索引要合并
(马蓉,文章1,出现次数1),(带着,1,1),(孩子,[1,2],[1,2]),
(王宝强,[1,2],[1,1]);(新欢,2,1),(结新欢,2,1),(熊乃瑾,2,1)
数据库 | java | lucene |
---|---|---|
varchar | String | StringField 或 TextField |
bigInt | Long | LongField |
int | int | IntField |
tinyInt | boolean | BooleanField |
。。。 |
4. lucene的使用
1. 导入Lucene的jar包
2. 编写代码
/**
* 建立索引文件
* 步骤
* 1. 创建文件对象
* 2. 利用分词创建索引, 创建完索引可以利用分词查看器查看当前索引的分词内容
* @throws IOException
* */
@org.junit.Test
public void createIndex() throws IOException {
Document doc = new Document();
//doc中的数据应该是调用代码将数据导入
//这里我们手动创建 数据 , 模拟读取数据库的过程
//创建 一个商品的数据索引
doc.add(new LongField("id", 12324, Store.YES));//yes表示索引创建完成之后允许被使用。
doc.add(new TextField("title", "iphoneX 我就是最XXX的手机", Store.YES));
//title 和img 的数据其实都是String类型的 , 但是如果使用TextField则会对内容进行分词
//如果使用StringField , 则会将字段作为一个最小 分词处理
doc.add(new StringField("img", "http://www.baidu.com/hjdfh.jpg", Store.YES));
doc.add(new DoubleField("price", 299, Store.YES));
//利用分词创建索引
//创建索引文件保存目录
Directory dir = FSDirectory.open(new File("./index"));
//使用标准分词器分词
Analyzer analyzer = new StandardAnalyzer();
//调用索引config对象对写出的索引文件进行参数设定
//Version一定要与导入的jar包相对应 , 否则报错
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer);
//使用Lucene内置的流写出索引文件
IndexWriter writer = new IndexWriter(dir , config);
writer.addDocument(doc);
writer.close();
dir.close();
}
3. 生成的索引为二进制文件 , 可以使用分词查看器查看![](https://i.imgur.com/o6SgILZ.jpg)![](https://i.imgur.com/bc8v0Va.jpg)![](https://i.imgur.com/RPE0cc1.png)
4. 观察分词结果 ,发现标准分词器 , 只能讲中文一个一个分割开 , 并不能将中文按照语义分割
5. 可以试用Luence中自带的中文分词器 , 修改代码![](https://i.imgur.com/PDR45fD.png)
6. 查看分词结果![](https://i.imgur.com/sSjMiYY.png)比用 标准分词器效果好一点 , 但是中文还是分的很烂
7. 引入第三方中文分词器(IKAnalyzer)修改代码![](https://i.imgur.com/JeuAD3k.png)查看分词结果![](https://i.imgur.com/OMehDDj.png) 可以看到具有语义的最小词被分了出来 。
8. 使用Lucene进行搜索
/**
* 使用索引进行查询
* @throws IOException
* */
@org.junit.Test
public void search() throws IOException {
//在索引中进行查询
Directory dir = FSDirectory.open(new File("./index2"));
IndexSearcher search = new IndexSearcher(IndexReader.open(dir));
Query query = new TermQuery(new Term("title" , "手"));//*代表检索所有的字段 , 可以检索单个字段如:tilte
TopDocs topDocs = search.search(query, 10);//第二个参数表示返回查询结果的条数
for(ScoreDoc sd : topDocs.scoreDocs) {
System.out.println("得分:"+sd.score);
Document doc = search.doc(sd.doc);
System.out.println(doc.get("id"));
System.out.println(doc.get("title"));
System.out.println(doc.get("img"));
System.out.println(doc.get("price"));
}
dir.close();
}
![](https://i.imgur.com/rSq12DR.png)
安装Solr
完成项目(京淘 简称jt)的其他配置
其中jt项目的配置文件放在jt/conf下 , 数据文件(即索引文件)放在jt/data中
将配置文件放到conf中 使用rz -E命令上传文件
schema.xml
id
solrconfig.xml
4.10.2
${solr.data.dir:}
${solr.hdfs.home:}
${solr.hdfs.confdir:}
${solr.hdfs.blockcache.enabled:true}
${solr.hdfs.blockcache.global:true}
${solr.lock.type:native}
true
false
${solr.ulog.dir:}
${solr.autoCommit.maxTime:15000}
false
${solr.autoSoftCommit.maxTime:-1}
1024
true
20
200
static firstSearcher warming in solrconfig.xml
false
2
explicit
10
title
explicit
json
true
title
true
json
true
{!xport}
xsort
false
query
explicit
velocity
browse
layout
Solritas
edismax
text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
title
100%
*:*
10
*,score
text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename
3
on
true
cat
manu_exact
content_type
author_s
ipod
GB
1
cat,inStock
after
price
0
600
50
popularity
0
10
3
manufacturedate_dt
NOW/YEAR-10YEARS
NOW
+1YEAR
before
after
on
content features title name
true
html
<b>
</b>
0
title
0
name
3
200
content
750
on
false
5
2
5
true
true
5
3
spellcheck
true
ignored_
true
links
ignored_
solrpingquery
all
explicit
true
text_general
default
text
solr.DirectSolrSpellChecker
internal
0.5
2
1
5
4
0.01
wordbreak
solr.WordBreakSolrSpellChecker
name
true
true
10
title
default
wordbreak
on
true
10
5
5
true
true
10
5
spellcheck
mySuggester
FuzzyLookupFactory
DocumentDictionaryFactory
cat
price
string
true
10
suggest
title
true
tvComponent
lingo
org.carrot2.clustering.lingo.LingoClusteringAlgorithm
clustering/carrot2
stc
org.carrot2.clustering.stc.STCClusteringAlgorithm
kmeans
org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm
true
true
name
id
features
true
false
edismax
text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
*:*
10
*,score
clustering
true
false
terms
explicit
title
elevator
100
70
0.5
[-\w ,/\n\"']{20,200}
]]>
]]>
,,
,,
,,
,,
,]]>
]]>
10
.,!?
WORD
en
US
text/plain; charset=UTF-8
5
dih-config.xml
*:*
dih-config.xml
将三个html文件存入conf目录下
admin-extra.html
http://www.apache.org/licenses/LICENSE-2.0
admin-extra.menu-bottom.html
http://www.apache.org/licenses/LICENSE-2.0
admin-extra.menu-top.html
http://www.apache.org/licenses/LICENSE-2.0
集成中文分词器
将dist下的两个jar包复制进lib中个jar包
#cp solr-dataimporthandler-* /home/software/solr-5.3.1/server/solr-webapp/webapp/WEB-INF/lib
将IKAnalyzer.cfg.xml 、 ext.dic 、 stopword.dic放到solr-5.2.1/server/solr-webapp/webapp/WEB-INF/classes (将自定义中文分词(如果使用默认可能未必最新,比如网络用语,专业名词都没有分词支持,需要自定义添加);有扩展字典,有停止字典(例如禁止网络用语骂人的话))
IKAnalyzer.cfg.xml
IK Analyzer 扩展配置
ik_ext.dic;
ik_stopwords.dic;
ext.dic (扩展分词)
电信3G手机
双卡
双待
ik_stopwords.dic(停止分词)
a
an
and
are
as
at
be
but
by
for
if
in
into
is
it
no
not
of
on
or
such
that
the
their
then
there
these
they
this
to
was
will
with
进入到solr的bin目录下 重启solr
./solr stop –all #停止服务
./solr start #启动服务
./solr restart #重启服务
6. 访问solr 创建core
7. 选择创建的核心工程
8. DIH数据导入添加完成之后 , 所有的数据库记录对应的doc索引就创建成功了
9. 测试
添加依赖
org.apache.solr
solr-solrj
5.2.1
org.wltea.analyzer
ik-analyzer
5.3.0
solr与spring整合 添加applicationContext-solrj.xml
代码
controller层
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@RequestMapping("search")
public String search(String q,Integer page,Model model) throws Exception{
try{
q=new String(q.getBytes("ISO8859-1"),"UTF-8");
}catch(Exception e ){
e.printStackTrace();
}
//准备一个分页数量rows
Integer rows=20;
List- itemList=searchService.queryItemList(q,page,rows);
model.addAttribute("itemList", itemList);
return "search";
}
}
service层
@Service
public class SearchService {
@Autowired
private HttpSolrClient client;
public List
- queryItemList(String q,Integer page,Integer rows) throws Exception{
if(null==page){
page=1;}
//起始位置
Integer start=Math.max(page, 1);
SolrQuery query= new SolrQuery();
query.setQuery("title:"+q);//"title:三星"
query.setStart(start);
query.setRows(rows);
//执行连接获取数据
QueryResponse response=client.query(query);
List
- itemList=response.getBeans(Item.class);
return itemList;
}