Solr(大数据的搜索)
一、solr 简介
Solr 就是一个搜索服务器,使用Lucene实现
Solr 和Lucene 关系
Lucene :好多接口 ,工具类,来帮助实现搜索
Solr :实现了很多接口,形成了自己的产品,用户只要部署我,就可以实现搜索功能
二、对比solr 搜索和数据库的搜索
Select * from where ? 搜索条件 name like ‘%name%’;
数据库通过搜索来搜索
Select * from where id = xx?
2.1 正排索引
(通过标题搜索,但是能通过单词搜索吗?)
静夜思 - >[
1 2 3 4
]
通过文档的id 或文档的标题来搜索文档。
2.2 倒排索引
通过文档里面的任何单词来搜索
通过文档里面的单词,语句来搜索文档
你背一下 举头望明月{
1 2 3 4
}
倒排索引的优化
2.3 速度对比
Mysql
Solr 大于mysql 百倍)
2.4 elsearch vs solr
Solr的静实时搜索能力>> elsearch
若是存储好之后搜索,则被称为静:
Elsearch的动搜索的能力>> solr
边存边搜索:动
Elsearch :提供了一个大数据处理的生态
Solr:生态太差
三、安装solr
在企业用solr4 的比较多一个点,因为用tomcat7的人多,因为用jdk1.7 以上的人多一点
3.1 下载solr4
3.2 solr 是一个web的产品,需要tomcat部署
Solr4 推荐tomcat7
3.3 安装tomcat7
3.3.1 下载tomcat7
3.3.2 上传到linux 里面
3.3.3 解压运行
3.4 将solr 部署在tomcat7里面
3.4.1 上传solr进去
3.4.2 解压solr
3.4.3 查询solr的war 包
3.4.4 将war 复制到tomcat7里面
停止tomcat7
cp solr.war /usr/local/tomcat7/apache-tomcat-7.0.92/webapps/
3.4.5 解压war
若没有unzip ,可以先安装
unzip solr.war -d ./solr
将solr 解压到当前的目录solr文件夹里面,若该文件夹不存在,则会自动创建
解压成功后,删除solr.war
3.4.6 给solr复制依赖
该文件夹里面的依赖还不够,缺少日志jar 的依赖,需要复制日志依赖过来
日志依赖在:
复制到solr的WEB-INF 里面
检查:
3.4.7 solr 需要一个solr-core
Solr 需要一个存储数据的地方,名称叫solr-core,在solr的WEB-INF/web.xml 文件里面配置
3.4.8 新建solr-home
Cd /usr/local/solr4
Mkdir solr-home
给solr-home 里面复制默认的配置文件
复制的源:
目标:
3.4.9 启动测试
四、Solr的分词使用
Mysql 数据库->表->行-> 列
Solr solr-core->没有表->文档的概念json{}-> 字段
4.1 创建solr 的core
默认的
4.1.1 新建文件夹
4.1.2 复制配置文件
4.1.3 页面创建
4.2 solr的分词
我想买个 大屏手机
4.2.1 solr 里面自带默认分词
4.2.2 添加中文分词
IK分词器
1 : 下载ik 分词
2:导入ik分词
将该jar 复制到WEB-INF/lib 里面
3:配置字段(需要添加自己的字段且字段类型)
在scheam.xml 里面添加该字段类型
将他放在text_en 上面就ok 了
<fieldType name="text_cn" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
修改完后,重启测试
4:配置分词(旧版没有效果,新版有效果)
停止分词:遇到一次词语后,我不分该词了
扩展:中国 中国人
将配置文件和字典复制到classpath 里面去:
Vi IKAnaly.cfg.xml
添加
新建一个ext.dic的文件
Vi ext.dic
五、使用java 操作solr
Java+solr = solrj
5.1 新建maven项目
5.2 添加依赖
<!-- https://mvnrepository.com/artifact/org.apache.solr/solr-solrj -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>4.10.4</version>
</dependency>
后面报错加的
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
5.3 测试
需要添加该jar
5.3.1 怎么导入数据
public static void main(String[] args) {
// 协议:Http sorl服务器的地址:http://192.168.231.143:8080/solr 操作那个core:sxt
String baseURL = "http://192.168.231.143:8080/solr/sxt";
HttpSolrServer solr = new HttpSolrServer(baseURL);
SolrInputDocument solrInputDocument = new SolrInputDocument();
solrInputDocument.setField("id", "1"); // 必须有个id的自动
solrInputDocument.setField("author", "ltd"); // 字段必须在系统里面有,可以在页面上查询
// {"id":"1","author":"ltd"} 这就是文档
try {
solr.add(solrInputDocument); // dml
solr.commit(); //dml 操作需要提交事务
System.out.println("导入成功");
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
5.3.2搜索数据
可以先在页面上搜索
public static void query() {
String baseURL = "http://192.168.231.143:8080/solr/sxt";
HttpSolrServer httpSolrServer = new HttpSolrServer(baseURL);
String q = "*:*" ; // 搜索的条件
SolrQuery solrQuery = new SolrQuery(q); // 构建条件
try {
QueryResponse query = httpSolrServer.query(solrQuery); // 执行搜索
SolrDocumentList results = query.getResults(); // 获取搜索的结果集合
System.out.println(results);
// {numFound=1,start=0,docs=[SolrDocument{id=1, author=ltd, author_s=ltd, _version_=1633858155821662208}]}
// numFound = 总条数 docs={搜索出来的内容} start :起始的条数(没有实际的意义)
} catch (SolrServerException e) {
e.printStackTrace();
}
}
六、增量的导入
6.1 设计实体类
6.2 设计接口
/**
* 商品导入服务的接口
* @author CodeLab
*
*/
public interface ImportService {
/**
* 从数据导入solr 里面
*/
void import2Solr();
/**
* 查询商品
*/
List<Goods> query(String keyword,int page,int size);
}
6.3 实现接口
@Service
public class ImportServiceImpl implements ImportService {
@Autowired
private GoodsMapper goodsMapper;
private int pageSize = 200; // 200 ,每次导入200条
@Autowired
private HttpSolrServer solrServer;
/**
* 从数据里面导入到solr 里面,要求:
* 第一次需要全部导入
* 后面都是增量的导入
*/
@Override
public void import2Solr() {
// 第一步查询数据库的商品(分页导入)
// 1 计算总页数
long total = goodsMapper.countByExample(null);//总条数
long totalPage = total % pageSize == 0?total / pageSize: (total / pageSize +1);
for (int i = 1; i <= totalPage; i++) {
PageHelper.startPage(i,pageSize); // 不涉及增量导入
List<Goods> goods = goodsMapper.selectByExample(null); // 全部查询时不行的,因为数据量太大,导致可以导入失败,我们可以把数据库的数据分批导入(数据库的分页查询)
List<SolrInputDocument> docs = goods2Docs(goods);
try {
solrServer.add(docs);
solrServer.commit();
System.out.println("第"+i+"导入完成");
} catch (SolrServerException e) {
e.printStackTrace();
System.out.println("第"+i+"导入完成");
} catch (IOException e) {
e.printStackTrace();
System.out.println("第"+i+"导入完成");
}
}
}
/**
* 将商品转换为一个solr的文档
* @param goods
* @return
*/
private List<SolrInputDocument> goods2Docs(List<Goods> goods) {
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
for (Goods gd : goods) {
SolrInputDocument solrInputDocument = new SolrInputDocument();
// 商品里面有很多字段,但是我们只需要导入能从页面搜索出来的字段 eg:goodsName,goodsImg,goodsPrice
Integer id = gd.getId();
String goodsName = gd.getGoodsName();
String goodsImg = gd.getGoodsImg();
BigDecimal goodsPrice = gd.getGoodsPrice();
Integer goodsCommentNum = gd.getGoodsCommentNum();
solrInputDocument.addField("id", id+"");
solrInputDocument.addField("goods_name", goodsName);//?goods_name 该字段必须在solr的系统里面有
solrInputDocument.addField("goods_img", goodsImg);
solrInputDocument.addField("goods_price", goodsPrice.doubleValue());
solrInputDocument.addField("goods_comment_num", goodsCommentNum);
docs.add(solrInputDocument);
}
return docs;
}
/**
* 分页搜索
*/
@Override
public List<Goods> query(String keyword, int page, int size) {
return null;
}
}
6.4 在solr 里面导入商品的字段
修改schema.xml
在
添加以下字段
<!-- 添加商品的字段
type; 字段的类型
indexed:该字段是否支持索引(只有设置为true字段,才能搜索)
stored:该字段是否需要存在在solr-core里面,不存在,则无法搜索
required:该字段是否为必填的
multiValued:该字段的类型是否为数组
-->
<field name="goods_name" type="text_cn" indexed="true" stored="true" required="true" multiValued="false" />
<field name="goods_img" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="goods_price" type="float" indexed="true" stored="true" required="true" multiValued="false" />
<field name="goods_comment_num" type="int" indexed="true" stored="true" required="true" multiValued="false" />
重启solr 测试
6.5 导入商品
public class SolrApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("classpath:spring-*.xml");
app.start();
ImportService importService = app.getBean(ImportService.class);
importService.import2Solr();
System.out.println("导入数据库的数据成功");
}
}
6.6 测试搜索