首先我们要了解什么是ik分词器( 摘自百度百科 )
ik 分词器简介:
从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目Lucene为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为 面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。
运行环境 :
授权协议: LGPL
开发语言: Java
操作系统: 跨平台
最新版本 :
当前最新版本为IKAnalyzer2012 (2012年停更)
1. 采用了特有的“正向迭代最细粒度切分算法“,支持细粒度和智能分词两种切分模式;
2.在系统环境:Core2 i7 3.4G双核,4G内存,window 7 64位, Sun JDK 1.6_29 64位 普通pc环境测试,IK2012具有160万字/秒(3000KB/S)的高速处理能力
3.2012版本的智能分词模式支持简单的分词排歧义处理和数量词合并输出。
4.采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符
5. 优化的词典存储,更小的内存占用。支持用户词典扩展定义。特别的,在2012版本,词典支持中文,英文,数字混合词语。
相关特性 :
采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。
采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。
对中英联合支持不是很好,在这方面的处理比较麻烦.需再做一次查询,同时是支持个人词条的优化的词典存储,更小的内存占用。
支持用户词典扩展定义。
针对Lucene全文检索优化的查询分析器IKQueryParser;采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。
实现数据库连接查询:
测试表结构:
创建一个maven项目,大致结构如下
1. pom.xml配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cn.etgroupId>
<artifactId>databaseartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<webVersion>3.1webVersion>
properties>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.5.9.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>com.janeluogroupId>
<artifactId>ikanalyzerartifactId>
<version>2012_u6version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-highlighterartifactId>
<version>4.7.2version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>MysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.38version>
dependency>
dependencies>
<build />
project>
2. 数据库四要素 application.properties 配置
spring.datasource.url=jdbc:mysql://localhost/food
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#解决乱码问题
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8
3 然后我们需要连接数据库,对其进行查询。
因为数据库中的数据并不像自己测试般那么一点数据,所以我们必须要批量查询
DataBaseDao.java / DataBaseDaoImpl.java
package cn.et.database.dao.impl;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import cn.et.database.dao.DataBaseDao;
@Repository
public class DataBaseDaoImpl implements DataBaseDao{
@Autowired
JdbcTemplate jdbc;
//查询数据库总行数
public int foodcount() {
String sql="select count(*) as foodCount from food";
return Integer.parseInt(jdbc.queryForObject(sql, java.lang.String.class));
}
//每页显示行数
public List
4.查询到的数据需要使用分词器来对其进行分词并存储,搜索时还要实现高亮等。
创建一个工具类,用于定义一个存储路径和分词器,搜索实现高亮。
IndexDemo.java
package cn.et.database.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.TextFragment;
import org.apache.lucene.search.highlight.TokenSources;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.stereotype.Component;
import org.wltea.analyzer.lucene.IKAnalyzer;
@Component
public class IndexDemo {
//Lucene索引文件路径
static String dir="E:\\lucence";
//定义分词器
static Analyzer analyzer = new IKAnalyzer();
/**
* 封裝一个方法,用于将数据库中的数据解析为一个个关键字词存储到索引文件中
* @param doc
*/
public void write(Document doc){
try {
//索引库的存储目录
Directory directory = FSDirectory.open(new File(dir));
//关联当前lucence版本和分值器
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_47, analyzer);
//传入目录和分词器
IndexWriter iwriter = new IndexWriter(directory, config);
//写入到目录文件中
iwriter.addDocument(doc);
//提交事务
iwriter.commit();
//关闭流
iwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//搜索
public List
5.查询数据,调用工具类,将数据存储,分词,实现高亮。
DataBase.java
package cn.et.database.controller;
import java.util.List;
import java.util.Map;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.et.database.dao.DataBaseDao;
import cn.et.database.util.IndexDemo;
@RestController
public class DataBase {
@Autowired
DataBaseDao dao;
@Autowired
IndexDemo indexDemo;
@GetMapping("/createIndex")
public String createIndex(){
//查询数据库,必须要批量查询
int fc = dao.foodcount();//查询总行数 8
int start = 0; //开始位置
int rows = 5; //每页行数
/*
* 0---4 5
* 5---9 5
* 10---14 5
*/
while(start<=rows){
//每拉取一次数据
List> queryFood=dao.queryFood(start, rows);
//获取字段
for(int i=0;i
//获取每行数据
Map lineData = queryFood.get(i);
//创建Document对象
Document doc = new Document();
//获取每列数据
Field foodid=new Field("foodid",lineData.get("foodid").toString(),TextField.TYPE_STORED);
Field foodname=new Field("foodname",lineData.get("foodname").toString(),TextField.TYPE_STORED);
Field price=new Field("price",lineData.get("price").toString(),TextField.TYPE_STORED);
Field imagepath=new Field("imagepath",lineData.get("imagepath").toString(),TextField.TYPE_STORED);
//添加到Document中
doc.add(foodid);
doc.add(foodname);
doc.add(price);
doc.add(imagepath);
//调用,创建索引库
indexDemo.write(doc);
}
start=rows+1;
}
return "成功";
}
//搜索,实现高亮
@GetMapping("/searchFood")
public List getFood(String keyWord) throws Exception{
return indexDemo.search("foodname", keyWord);
}
}
6.启动 TestMain.java
访问 http//localhost:8080/createIndex 将数据分词,存储(返回成功 ok )
package cn.et.database;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestMain {
public static void main(String[] args) {
SpringApplication.run(TestMain.class, args);
}
}
7.接下来我们要实现一个简单的前端搜索页面,便于我们判断,使用 juqery+html
将 jquery-3.1.0.min.js 文件丢到webapp下
创建一个html文件
search.html
<html>
<head>
<meta name="keywords" content="keyword1,keyword2,keyword3">
<meta name="description" content="this is my page">
<meta name="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="jquery-3.1.0.min.js">script>
<script type="text/javascript">
$(function(){
$("#searchBtn").click(function(){
$.ajax({
url:'/searchFood',
data:'keyWord='+$("input[name='keyWord']").val(),
success:function(jd){
$("div[name='c']").remove();
for(var i=0;ivar html=
""+
""
+jd[i].foodname+""+
""+jd[i].foodname+"价格是:"+jd[i].price+""+
"" +
""
$("#foodDiv").append(html);
}
}
})
})
})
script>
head>
<body>
<div align="center">
<img src="log.png" style="height:55px;width: 190px;"><br>
<table>
<input type="text" name="keyWord" style="width:450px; height:30px;">
<input type="button" id="searchBtn" value="搜索一下" style="height: 37px;background-color: #38f">
table>
<div id="foodDiv" align="justify">
div>
div>
body>
html>
启动,访问 http//localhost:8080/searchFood 搜索