第一个分布式项目总结(3)——Solr

版权声明:Songcz原创,如有转载请注明出处 https://blog.csdn.net/weixin_43701058/article/details/90144223

Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。
在本项目中的应用:索引库
0.总述:老规矩先看架构图。
在这里插入图片描述
即如图所示搜索服务的实现。
我们先看下Solr的应用效果,即搜索服务的页面表现。在这里插入图片描述
在搜索服务中,查询数学相关的课程。即可显示所有“数学”相关课程,并返回总数。
1.为什么使用solr
1.减轻MySQL数据库压力,MySQL也可以实现搜索功能,可以通过"like"模糊查询,但是效率低,速度慢,《高性能MySQL》中就不建议使用like的方式。
2.建立MySQL索引,其实这个方式相比于数据库直接查询,效率有了极大的提高,但索引对于中文的支持表现的并不好,而且在数据库中索引本质上也是一张表,其是一种空间换时间的行为,为了程序的扩展性,考虑到以后数据量的大小,有必要减小数据表数量,而Solr独立于MySQL之外,并可以通过配置IK分词器解决中文分词问题,所以采用Solr这种相对成熟且方便的技术。
2.业务域配置
Solr怎么和tomcat结合部署这里就不进行介绍,有需要的朋友可以查看相关文档。
schema.xml配置:
首先添加IK分词器
1、把相关Jar包添加到solr工程的lib目录下
2、把扩展词典、配置文件放到Solr工程的WEB-INF/classes目录下。

<fieldType name="text_ik" class="solr.TextField">
  <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

对业务域配置,type制定使用自定义的FieldType。

<field name="course_title" type="text_ik" indexed="true" stored="true"/>
<field name="course_light_point" type="text_ik" indexed="true" stored="true"/>
<field name="course_cedit"  type="long" indexed="true" stored="true"/>
<field name="course_teacher" type="text_ik" indexed="true" stored="true"/>
<field name="course_image" type="string" indexed="false" stored="true" />
<field name="course_category_name" type="string" indexed="true" stored="true" />
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="course_title" dest="item_keywords"/>
<copyField source="course_light_point" dest="item_keywords"/>
<copyField source="course_teacher" dest="item_keywords"/>
<copyField source="course_category_name" dest="item_keywords"/>

3.连接Solr
a.添加至索引库
使用SolrJ连接Solr。
感觉上和Jedis连接Redis差不多,SolrJ连接Solr也是靠“对象”来完成的。

0、创建一个SolrServer对象。创建一个和Solr服务的连接。HttpSolrServer。(这里可以看出来是基于Http协议连接solr的)
1、创建一个文档对象。SolrInputDocument。
2、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。
3、把文档添加到索引库

这有需要一堆对象,找对象这种事咱还是交给Spring来完成。

	<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg index="0" value="http://solr地址:8080/solr/业务域名称"/>
	</bean>

OK就这么简单,ps:头别忘了写
代码实现

public EasResult importAllCourses() {
		try {
			//查询课程列表
			List<SearchCourse> courseList = courseMapper.getCourseList();
			//遍历课程列表
			for (SearchCourse searchCourse : courseList) {
				//创建文档对象
				SolrInputDocument document = new SolrInputDocument();
				//向文档对象中添加域
				document.addField("id", searchCourse.getId());
				document.addField("course_title", searchCourse.getTitle());
				document.addField("course_light_point", searchCourse.getLight_point());
				document.addField("course_image", searchCourse.getImage());
				document.addField("course_teacher", searchCourse.getTercher());
				document.addField("course_category_name", searchCourse.getCategory_name());
				//把文档对象写入索引库
				solrServer.add(document);
			}
			//提交
			solrServer.commit();
			//返回导入成功
			return EasResult.ok();
		} catch (Exception e) {
			e.printStackTrace();
			return EasResult.build(500, "数据导入时发生异常");					
		}
	}

b.查询索引库
我这个比较简单就一个查询条件,一个key就OK了。

public SearchResult search(String keyword, int page, int rows) throws Exception {
		//0.创建一个SolrQuery对象
		SolrQuery query = new SolrQuery();
		//1.设置查询条件
		System.out.println(keyword);
		query.setQuery(keyword);
		//2.设置分页条件
		if (page <=0 ) page =1;
		query.setStart((page - 1) * rows);
		query.setRows(rows);
		//3.设置默认搜索域
		query.set("df", "course_title");
		//4.开启高亮显示
		query.setHighlight(true);
		query.addHighlightField("course_title");
		query.setHighlightSimplePre("<em style=\"color:red\">");//前缀	
		query.setHighlightSimplePost("</em>");//后缀
		//5.调用dao执行查询
		SearchResult searchResult = searchDao.search(query);
		//6.计算总页数
		long recordCount = searchResult.getRecordCount();
		int totalPage = (int) (recordCount / rows);
		if (recordCount % rows > 0) 
			totalPage ++;
		//7.添加到返回结果
		searchResult.setTotalPages(totalPage);
		//8.返回结果
		return searchResult;
		
	}

4.缺点:
Solr有这么多优点,但也存在问题,这种分布式存储的共同问题就是数据的一致性,突出表现为MySQL数据和Solr数据不一致,直接对MySQL数据进行的操作后,Solr数据依然没有变化…
解决办法:采用消息队列,点对点方式,本项目使用的ActiveMQ。后续博客会有相关介绍。
5.拓展:Solr原理
以防不测,还是看看…Solr这东西实现是个什么原理。
Solr是一个高性能,基于Lucene全文搜索服务器

1.顺序扫描法:对5个文档依次查找,包含目标字段的文档就记录下来,最后查找的结果可能是在2,3文档中,这种查找方式叫做顺序扫描法。
顺序扫描法在文档数量较少的情况下,查找速度还是很快的,但是当文档数量很多时,查找速度就差强人意了。
2.全文检索:对文档内容进行分词,对分词后的结果创建索引,然后通过对索引进行搜索的方式叫做全文检索。
全文检索就相当于根据偏旁部首或者拼音去查找字典,在文档很多的情况,这种查找速度肯定比你一个一个文档查找要快。

Solr/Lucene采用的是一种反向索引。
所谓反向索引:就是从关键字到文档的映射过程,保存这种映射这种信息的索引称为反向索引。
OK这里就这样简单介绍下,底层原理其实相当复杂,有兴趣的朋友可以点击这里查看。

猜你喜欢

转载自blog.csdn.net/weixin_43701058/article/details/90144223