通过前面几节的了解,我们对 solr 有了一些了解,对一些基本概念、语法也有了初步的认识,那么很多没有接触过搜索引擎的小伙伴可能会问,这东西到底有什么用,在自己的项目中能发挥什么作用,结合我们自己的项目,简要做个演示。
需求分析
相信很多人都用过类似淘宝或者京东的产品搜索功能,输入想要查找的商品,点搜索很快列出一堆你想要的东东,我们的产品也想实现这个功能。
我们都知道数据库的瓶颈主要在 IO 这块,虽然通过分库分表能分担一部分负载,但当网站访问量比较大的时候,不应该也不可能搜索一次都去执行一次数据库 IO 操作,这个时候 Solr 也就派上用途了,我们可以通过将产品相关数据刷到 Solr 的搜索实例中,通过 Solr 应用服务器对外提供 Rest 查询接口,定时去更新数据,刷新搜索索引,这样就大大降低了查询数据库服务器的压力。
数据导入
那么问题来了,如果将数据库相关数据导入搜索实例中呢?前面我们使用了 bin/post
将 json 文档直接导入搜索实例,接下来我们看下如何将 mysql 中表数据导入到搜索实例中。
使用DIH(DataImportHandler)从数据库导入数据
-
首先数据库准备一张表
CREATE TABLE `comment` ( `id` INT(11) NULL DEFAULT NULL, `writetime` VARCHAR(50) NULL DEFAULT NULL, `title` VARCHAR(500) NULL DEFAULT NULL )
-
往表里面插入几条测试数据
INSERT INTO `test`.`comment` (`id`, `writetime`, `title`) VALUES (10001, '2015-04-11', 'Step 1: Set up a personal account'); INSERT INTO `test`.`comment` (`id`, `writetime`, `title`) VALUES (10002, '2015-04-12', 'Step 2: Choose your plan'); INSERT INT3 `test`.`comment` (`id`, `writetime`, `title`) VALUES (10003, '2015-04-13', 'Step 3: Go to your dashboard'); INSERT INTO `test`.`comment` (`id`, `writetime`, `title`) VALUES (10004, '2015-04-14', 'There were problems creating your account.'); INSERT INTO `test`.`comment` (`id`, `writetime`, `title`) VALUES (10005, '2015-04-15', 'You will occasionally receive account related emails. We promise not to share your email with anyone.'); INSERT INTO `test`.`comment` (`id`, `writetime`, `title`) VALUES (10006, '2015-04-16', 'Use at least one lowercase letter, one numeral, and seven characters.');
-
导入相关jar包 在
solr-5.0.0/server/solr/test/conf/solrconfig.xml
加入如下代码<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-dataimporthandler-.*\.jar" />
-
配置handler 在
solr-5.0.0/server/solr/test/conf/solrconfig.xml
加入如下代码<requestHandler name="/dataimport" class="solr.DataImportHandler"> <lst name="defaults"> <str name="config">db-data-config.xml</str> </lst> </requestHandler>
-
配置数据源,源数据与索引的隐射关系 在
solr-5.0.0/server/solr/test/conf/下新建db-data-config.xml
,配置如下:<dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/test" user="root" password="root"/> <document> <entity name="comment" query="SELECT id, DATE_FORMAT(writetime, '%Y-%m-%dT%TZ') as 'writetime', title from comment" deltaImportQuery="SELECT id, DATE_FORMAT(writetime, '%Y-%m-%dT%TZ') as 'writetime', title from comment where id='${dih.delta.id}'" deltaQuery="SELECT id FROM comment WHERE DATE(updatetime) >= '${dih.last_index_time}' OR DATE(writetime) >= '${dih.last_index_time}'"> <field column="id" name="id"/> <field column="writetime" name="writetime"/> <field column="title" name="title"/> </entity> </document> </dataConfig>
注:查询 sql 可以是多表关联查询,只要查询字段跟下面的 field 对应起来就可以。另外 field 对应的name值必须在 config 目录下的 schema.xml 文件中存在。如上述的 writetime 不存在,则在schema.xml中添加
<field name="writetime" type="tdate" indexed="true" stored="true"/>
indexed 表示需不需要建立索引,以便之后对这个 field 进行查询;
stored 表示需不需要随索引同时存储这个 field 本身的内容,以便查询时直接从结果中获取该内容,一般大数据(比如文件内容本身)不会和索引一起保存,节省资源,防止索引过大。 索引本身和被索引的内容要分清,不理解的话,倒排索引:http://zh.wikipedia.org/wiki/
倒排索引
6.Reload test 搜索实例,利用图形界面执行dataimport
因为这个文件我已经导过了,所以上面显示是 reload,第一次使用时有一点点差别。导完数据以后我们查询验证下 http://localhost:8080/solr/test/select?q=title%3Astep&wt=json&indent=true
返回结果:
{
"responseHeader":{
"status":0,
"QTime":2,
"params":{
"indent":"true",
"q":"title:step",
"wt":"json"}},
"response":{"numFound":3,"start":0,"docs":[
{
"id":"10002",
"title":["Step 2: Choose your plan"],
"writetime":"2015-04-10T00:00:00Z",
"_version_":1498574060831899648},
{
"id":"10001",
"title":["Step 1: Set up a personal account"],
"writetime":"2015-04-10T00:00:00Z",
"_version_":1498574060739624960},
{
"id":"10003",
"title":["Step 3: Go to your dashboard"],
"writetime":"2015-04-10T00:00:00Z",
"_version_":1498574060832948224}]
}}
这里面我们使用的是 title:step
将 title 包含 step 的三条记录都查了出来。
编程的方式来自定义导入(这个编程部分再讲)
当然除了数据库数据,Solr 还能导入 csv,json,word,pdf,这部分有兴趣可以自己去试验下。
至此,一个简单的 Solr 的应用演示算是完成了。