Solr学习记录

摘要:对Solr进行学习。

Day 1 搭建Solr环境,并使用Java调用Solr接口

1.1环境搭建

我在初步在Mac上使用HomeBrew进行管理安装软件,使用brew命令进行安装4.10.4版本的Solr,命令如下:
首先获取Homebrew的versions包进行版本管理:

1
brew tap homebrew/versions

之后brew回去github上下载该版本管理包

随后,获取在brew服务上的Solr版本:

1
brew install homebrew/versions/solr

如下图所示:
Alt text

选取Solr4进行安装,起会自动安装Solr4.10.4的所有文件。
完成安装之后,cd到该目录下执行:

1
/usr/local/Cellar/solr4/4.10.4/bin/solr4 start

为了方便起见,将该执行的命令行代码写入alias,方便之后运行,结果如下:
Alt text
在本地端口8983开启Solr的HTTP服务。完成Solr环境搭建。访问效果如下:
Alt text

1.2 使用Solr的HTTP服务进行初步Query查询

使用Solr的Web服务进行查询,由于没有Data数据,所以尝试测试,访问如下URl:http://localhost:8983/solr/query?debug=query&q=test
该URL是对query进行查询,query参数为test,并对其进行debug。在浏览器对该URl进行访问之后,Solr以Json的形式返回给浏览器查询数据,数据如下图所示:
Alt text
由于没有数据,故responce的numFound数量为0.

1.3 用Java项目调用Solr接口

目前使用的是Solr的HttpServer,在Java代码中使用该服务接口,拼接参数进行查询。
使用Maven进行Solr包的引入,在pom.xml中新增:

1
2
3
4
5
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>4.10.4</version>
</dependency>

Maven将自动下载4.10.4 Solr包的所有依赖。引入Solr的Jar包之后,编写测试代码,测试是否能使用Solr的HttpServer接口服务,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.ModifiableSolrParams;

/**
* Created by huangguoxin on 16/7/21.
*/

public class TestSolrMain {

public static void main(String args[]){
SolrServer server = new HttpSolrServer("http://localhost:8983/solr");

ModifiableSolrParams params = new ModifiableSolrParams();
// 查询关键词
params.set("q", "test");
// 分页,,start=0就是从0开始,,rows=5当前返回5条记录,,,第二页就是变化start这个值为5就可以了。
params.set("start", 0);
params.set("rows", 5);
params.set("wt","json");
// 排序,,如果按照id 排序,,那么将score desc 改成 id desc(or asc)
params.set("sort", "id desc");

// 返回信息 * 为全部 这里是全部加上score,如果不加下面就不能使用score
params.set("fl", "*,score");

QueryResponse response = null;
try {
response = server.query(params);
} catch (SolrServerException e) {
e.printStackTrace();
}
// 搜索得到的结果数
System.out.println("Find:"+ response.getResults().getNumFound()+"\n\n");

// 输出结果
for(SolrDocument doc:response.getResults())
{
System.out.println("id: " + doc.getFieldValue("id").toString());
System.out.println("title: " + doc.getFieldValue("title").toString()+"\n");
}
}
}

运行结果应该为0,如下图所示:
Alt text

1.4 Day2学习计划

  • 1、尝试导入数据,并且设置Solr中的sechma.xm的field,能过完成初步的有数据的查询。
  • 2、熟悉Solr的不同语法规则,并进行时间操作。
  • 3、尝试编写JavaEE项目,能对查询数据进行展示与高亮处理。

Day2 学习记录

2.1 将Solr服务放置在Tomcat下运行过程记录

复制solr-4.10.4/example/webapps中的solr.war文件到tomcat安装目录中的webapps文件夹下,首先cd到Solr目录进行复制。

1
cp -r solr.war /Users/huangguoxin/Tomcat/apache-tomcat-7.0.67/webapps

运行tomcat。(忽略怎么运行tomcat),tomcat会自动解压solr.war文件。
删除solr.war文件。(不然每次启动tomcat都会发布一次)
回到tomcat的webapps目录下,打开solr/WEB-INF/web.xml文件。
找到其中的注释代码段,解开注释并添加自己的Solrhome路径。

1
2
3
4
5
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>/Users/huangguoxin/Tomcat/solr</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>

回到solr目录,打开文件夹:solr/example/solr,复制所有内容到solrhome中(此处我的solr存在Tomcat目录下)

1
cp -r solr /Users/huangguoxin/Tomcat

将solr/example/lib/ext下所有jar包复制到tomcat的webapps/solr/WEB-INF/lib下。

1
cp -r ext/ /Users/huangguoxin/Tomcat/apache-tomcat-7.0.67/webapps/solr/WEB-INF/lib

运行Tomcat:http://localhost:8080/solr,将看到如下画面:
Alt text

2.2 为Solr添加Core

  • 1、在solrhome目录下,新建一个mycore文件夹。
  • 2、在解压的solr/example/multicore目录中,复制core0文件夹到solrhome/mycore中。
  • 3、在solrhome中新建一个文件夹:mydocs
  • 4、复制解压的solr-4.10.0/example/exampledocs下的post.jar到solrhome/mydocs中
  • 5、复制解压的solr-4.10.0/example/multicore/exampledocs下的ipod_other.xml文件到solrhome/mydocs中
  • 6、在solr web page中新建core:
    Alt text
    注意事项为:InstanceDir要选择你自己设定的Solrhome的文件位置,不然Solr服务无法找到conf里的schema.xml等配置文件文件,dataDir同InstanceDir。
  • 7、完成配置之后,重启Tomcat服务。
  • 8、导入XML文件进入Solr:

    • 在Terminal运行如下语句将你的docs文件导入Solr;

      1
      java -Durl=http://localhost:8899/solr/mycore/update -Ddata=files -jar post.jar ipod_other.xml
    • 出现问题1:Error: Unable to access jarfile post.jar

    • 该问题主要是因为没在mycore/core0/mydocs目录下进行进行操作,而在其他目录下进行操作。所以出现该问题。
    • 出现问题2:implePostTool: WARNING: Solr returned an error #400 (Bad Request) for url: http://localhost:8080/solr/mycore/update
    • 该问题主要的原因是你的core中的schema.xml的filed与你上传的xml文件中的field格式不匹配,所以无法上传。应该人为设置sechema.xml文件的field,或者设置你要上传xml文件的field name。这样再使用URL上传就能上传xml文件。如图所示:
      Alt text
      完成上传xml文件。这里的docs.xml是我自己人为设置的类型,并进行上传测试。没有修改schema.xml文件,docs.xml文件如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <add>
      <doc>
      <field name="id">F8V7067-APL-KIT</field>
      <field name="type">Belkin</field>
      <field name="name">Belkin Mobile Power Cord for iPod w/ Dock</field>
      </doc>
      <doc>
      <field name="id">IW-02</field>
      <field name="type">Belkin</field>
      <field name="name">iPod &amp; iPod Mini USB 2.0 Cable</field>
      </doc>
      </add>
    • 在Web Page 验证xml上传是否成功。
      Alt text

  • 使用Java端测试Solr链接,修改其中SolrServer构造函数即可SolrServer server = new HttpSolrServer("http://localhost:8080/solr/mycore");并在查询参数上设置params.set("q","type:Belkin"),运行结果:
    Alt text

Day3 Solr DataImortFromMysql

配置Solr服务使其导入Mysql数据库中的数据。

3.1 DouyuCrawler库Data

之前爬取的斗鱼弹幕总计500W行数据可以在此使用Solr进行检索。

3.2 配置Solr

3.2.1

在之前配置了Solrhome在Tomcat服务器上,Solrhome的位置为:/User/yourname/Tomcat/solr
该目录下存在的项目结构是:
Alt text
你必须提供solr.xml,solrconfig.xml 和schema.xml这三个文件告诉Solr如何工作.Solr默认将索引数据存储在data目录下。
solr.xml指定Solr core的配置选项,同时支持自定义配置多个cores.
solrconfig.xml控制高级行为。例如,你可以指定一个替代data目录的路径.
schema.xml描述Solr建立索引的文档格式。其中,你可以定义文档为多个field的一个集合。你需要同时定义field的type和field本身。Field Type的定义很强大,包括Solr对输入的field的处理过程和如何搜索。

3.2.2

之后加入DataImportHandler,在solr/mycore/core0/conf/solrconfig.xml中添加requestHandler:

1
2
3
4
5
6
<requestHandler name="/dataimport"   
class="org.apache.solr.handler.dataimport.DataImportHandler">

<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>

所谓的DataImportHandler提供一种可配置的方式向solr导入数据,可以一次全部导入,也可以增量导入。可以实现:

  • 1、能够读取关系数据库中的数据。
  • 2、通过可配置的方式,能够将数据库中多列、多表的数据生成solr文档,能够通过solr文档更新solr
  • 3、提供通过配置文件就能够导入所有数据的能力
  • 4、能够发现并处理 由insert、update带来的变化
  • 5、能够配置”完全导入”和”增量导入”的时间
  • 6、让读取xml文件,并建立索引成为可配置。
  • 7、能够将 其他的数据源(例如:ftp,scp,etc)或者其他格式的文档(Json,csv)以插件的形式集成到项目中。

使用DataImportHandler需要向在Solrhome中添加Jar包,在core中添加lib文件夹,向lib中添加jar包,即如下图结构:
Alt text
其中solr-dataimporthandler-4.10.4.jar包在我的solr源文件的../libexec/dist下,使用cp命令拷贝即可。mysql的链接jar包略去不表。

3.2.3 创建data-config.xml

编写data-config-comment.xml,此文件用于描述如何查询MySQL数据,如何将数据变换导入索引。
使用的数据库叫DouyuCrawler,其中有个表叫Danmaku,代表斗鱼弹幕
其中:
entity对应MySQL数据库表中的一行
query对应全库导入的SQL查询
queryImportQuery 对应增量导入的SQL查询
deltaQuery对应增量导入获取最新修改的行ID,这些ID用于queryImportQuery,SQL的含义中:

1
DATE(updatetime) >= '${dih.last_index_time}' OR DATE(writetime) >= '${dih.last_index_time}

表示弹幕的更新时间updatetime,或者弹幕的写入时间writetime比上一次的导入时间$(dih.last_index_time)还大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<dataConfig>  
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/DouyuCrawler"
user="username"
password="password"
/>

<document name="Danmuku" >
<entity name="Danmuku"
query="select _id,uid,snick,content,date,rid from Danmaku"
deltaImportQuery="select _id,uid,snick,content,date,rid from Danmaku where _id
='${dataimporter.delta.id}'"

deltaQuery="select _id from Danmaku DATE(updatetime) >= '${dih.last_index_time}' OR DATE(writetime) >= '${dih.last_index_time}'">

<field column="_id" name="_id" />
<field column="uid" name="uid" />
<field column="snick" name="snick" />
<field column="content" name="content" />
<field column="date" name="date" />
<field column="rid" name="rid" />
</entity>
</document>
</dataConfig>

3.2.4配置schema.xml索引类型

1
2
3
4
5
6
7
<!-- general -->
<field name="_id" type="string" indexed="true" stored="true" required="true"/>
<field name="uid" type="string" indexed="true" stored="true" multiValued="true" />
<field name="snick" type="string" indexed="true" stored="true" />
<field name="content" type="string" indexed="true" stored="true"/>
<field name="date" type="tdate" indexed="false" stored="true"/>
<field name="rid" type="string" indexed="true" stored="true" multiValued="true" />

其中的字段含义:

1
2
3
4
5
6
7
8
<!--field属性说明:
filed字段用于定义数据源字段所使用的搜索类型与相关设置.
name:数据源字段名,搜索使用到.
type:搜索类型名例如中文ika搜索名text_ika,对应于fieldType中的name.不需要分词的字符串类型,string即可,如果需要分词,types中配置好的分词type。
indexed:是否被索引,只有设置为true的字段才能进行搜索排序分片(earchable, sortable, facetable)。
stored:是否存储内容,如果不需要存储字段值,尽量设置为false以提高效率。
multiValued:是否为多值类型,SOLR允许配置多个数据源字段存储到一个搜索字段中。多个值必须为true,否则有可能抛出异常。
-->

3.2.5 导入数据

配置完这几个配置文件之后,开启tomcat服务,进入http://localhost:8080/solr/#/mycore/dataimport//dataimport每个人的路径可能不同,选中数据上传页面的Entity下来框,选择自己的Entity,此处我的Entity为Danmuku,选中之后点击执行即可导入。如果你的数据量不是很大的话,可能几秒钟就能导入生成索引,如果不是,则极有可能报错。此处我作为测试数据量为16000行数据,总体量为1.79M左右,导入时间为3s。如图:
Alt text
如果长时间不跳转到成功页面,则极有可能是如下错误:

3.2.6 找不到html文件错误

从Web页面查看Solr的log信息:
Alt text
日志提示有几个html文件找不到,我们可以在solr的解压安装目录下可以找到,如图:
Alt text
将其中这三个拷贝到你的Solrhome中的core的conf文件夹下,然后我们需要清掉索引目录重新执行dataimport操作,如图删除index文件夹和tlog文件夹:
Alt text
然后重启我们的tomcat,重新执行dataimport操作即可。随后我们对其进行query操作,成功结果如下图:
Alt text

3.3 配置IKA分词器

1、访问该:

http://code.google.com/p/ik-analyzer/downloads/detail?name=IK%20Analyzer%202012FF_hf1.zip&can=2&q=

进行下载IKA分词包。
2、解压文件后,在你的Solrhome下的core中创建一个文件夹名为:lib,将解压之后的:

  • IKAnalyzer.cfg.xml、
  • IKAnalyzer2012FF_u1.jar、
  • stopword.dic

3、修改Solrhome\core\conf\文件夹下的schema.xml.在中增加如下内容:、

1
2
3
4
5
6
7
<!--配置IK分词器-->
<fieldType name="text_ik" class="solr.TextField">
<!--索引时候的分词器-->
<analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
<!--查询时候的分词器-->
<analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

4、启动Tomcat,在浏览器中输入http://localhost:8080/solr ,在页面左侧菜单中选择Core为mycore,点击Analysis(漏斗形状)菜单,在右侧页面Filed Value文本框中输入要测试分词的中文串.
5、在Field Value下方,Analyse FieldName/FieldType中选择text_ik,然后点击左侧Analyze Value按钮,就能看到分词结果。如下图所示:
Alt text
6、出现的问题:
首先主要你的Solr版本是哪个,如果是3.x版本的用IKAnalyzer2012_u6.zip如果是4.x版本的用IK Analyzer 2012FF_hf1.zip,一定要对应上,要不然会配置失败。

3.4 使用中文分词器查询弹幕内容

3.4.1 500W弹幕数据生成索引

与前文导入方法相同,使用Solr提供的Web页面进行导入Mysql中的数据。导入效果如下:
1、导入数据结果图:
Alt text
将Mysql 库中的500W行弹幕数据导入Solr,sql文件大约499MB,耗时3分钟左右,成功导入图如下:
Alt text
2、进行中文分词查询:
对弹幕信息进行初步的分词查询,结果如下:
Alt text
Alt text

使用Solrj进行查询

方式与上文提到相同:同样是编写Java代码,solrJ可以看成是solr的java版客户端,提供基本的索引维护、检索等功能。solrJ和solr服务端有两种“沟通”方式:第一,利用http进行通信。第二,直接访问solrCore(solr配置文件、索引文件等),不需要http通信(without http)。这边我使用的是http通信的方式。
结果如下所示:
Alt text
这边使用了Maven+Springboot进行环境搭建与使用。

Day4学习记录

4.1 Solr语法实践与查询结果展示

4.1.1 Solr基础语法

4.1.1.1 基础查询语法

查询的字段格式一般是: 字段名: 字段值
在生成的URL中,“:”(冒号)会被转义为变成“%3A。”

在现在的项目中需要对客户端的MAC地址进行查询,例如:7C:6E:BE:…..这样的MAC地址进行Solr查询,原意进行如下查询:q=macAddr:”7C:6E:BE“ 最后被Solr变成了:q=macAddr:”7C“,这就已经不是所需要的查询了

在SolrJ中为Java代码提供了一个工作类,提供给客户端对特殊字符转义的处理,如下代码所示:

1
2
import org.apache.solr.client.solrj.util.ClientUtils;
String escapedKw = ClientUtils.escapeQueryChars(kw);

solr特殊字符包含如下:

  • – && || ! ( ) { } [ ] ^ “ ~ * ? : \ 外加 空格

对冒号将转义如下:
Alt text
最主要的是时间的转换,不是我们熟知的yyyy-MM-dd HH:mm:ss 要转换撑Solr中的时间表示形式,如下代码所示:

1
2
3
4
import org.apache.commons.lang.time.FastDateFormat;
String date1 = FastDateFormat.getInstance(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(
c.getStartTime().getTime())

Alt text

4.1.1.2 与、或、非和范围查询语法

Solr的查询语法默认的分割符是OR

1
2
+solr +search facet -highlight 这句话与下句等同
solr AND search OR facet NOT highlight

4.1.1.3 分组语法

4.2 使用SpringBoot对Solr进行查询

首先创建SpringBoot,添加Maven的SolrJ依赖,之后设计SolrUtil工具类设计。

4.3 对数据进行上传处理

Day5 学习记录(搭建Zookeeper和SolrCloud集群)