Solr学习使用笔记(一)
一,Solr的目录结构
将下载的zip包解压到不含中文的目录即可使用,此处需要介绍一下Solr的目录结构,也就是初学者应该知道的几个地方.
首先在第一层目录中需要知道的是contrib和dist,这两个文件夹里面存放的是solr所要依赖的jar包,例如后面solr的数据库数据导入所需要的jar包就是需要拷贝到此处.再一个重要的文件件就是example文件夹.这里面存放的是solr的运行案例和内置的jetty服务器.Solr就是一个web服务.
进入example文件夹
需要注意的几点一是solr文件夹,里面存放的是索引库和配置信息,solr-webapp和webapps里面存放的solr.war,也就是solr服务,最后一个需要注意的地方就是start.jar,这个文件是用来运行jetty容器的.
二,启动jetty服务器,发布solr服务
在cmd中执行Java -jar start.jar 启动jetty服务器,并且访问
三:将服务发布到Tomcat容器中
1,将webapps中的solr.war拷贝到tomacat中的webapps中
2,解压并添加solr需要的依赖包,此处主要需要的是ik分词器的包,日志包
3, 修改Tomcat配置文件,指向Solr的索引库及配置目录。
在bin文件夹中的catalina.bat的开头添加
set "JAVA_OPTS"=-Dsolr.solr.home="路径"
,
4,启动tomcat,双击bin文件夹中的startup.bat
启动闪退,原因是删了之前的项目,但是,没有在server.xml中去除残留项目信息,打开server.xml,
<ContextdocBase="D:\Software\apache-tomcat-7.0.52\webapps\CRM"path="/CRM" reloadable="true"source="org.eclipse.jst.jee.server:CRM"/>删除这段context包含的内容.
启动报错,发现solr的路径配错.斜杠写反了
org.apache.solr.common.SolrException: Could not load conf for core collection1: Error loading solr config from d:/solr\collection1\conf\solrconfig.xml |
再次报错发现8009端口被占用
<!--Define an AJP 1.3 Connector on port 8009 -->
<Connector port="9009" protocol="AJP/1.3"redirectPort="8443"/>
再次启动
成功,访问http://localhost:80/solr/#/成功
四,Core目录介绍
Solr中core指的是每一个索引库,就像mysql中的每一个数据库,在solr的自带的core,collection1下存在一个conf文件夹和data文件夹,,在conf中主要存放的是配置信息,data存储的是索引的数据.conf配置中需要了解的是约束配置文件schema.xml和索引配置文件solrconfig.xml.
先从collection1中拷贝多一个索引库命名为coreTest,进行配置文件等的修改.
1,在core.properties文件中需要更改内容,是名称和文件夹名和里面的name一致
name=coreTest |
2,更改约束文件schema.xml
Schema.xml(注释在文档中)
<?xml version="1.0" encoding="UTF-8" ?> <schema name="example" version="1.5"> <!-- field标签中包的是索引库中的字段version和root是自带的不可删除--> <field name="_version_" type="long" indexed="true" stored="true"/> <field name="_root_" type="string" indexed="true" stored="false"/> <!-- 这里是可以自定义的字段,name是名称type是配置文件中所定义的类型,stored是是否存储,required表示是否必须,multiValued表示值是否多个--> <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> <field name="price" type="long" indexed="true" stored="true"/> <field name="text" type="text_general" indexed="true" stored="false" multiValued="false"/> <!--这里是动态字段,即匹配符字段,由于solr中未定义的字段不可存储,所以在此处扩展动态字段,使得可存储的字段更多--> <dynamicField name="*_i" type="int" indexed="true" stored="true"/> <!--uniqueKey指定唯一标识--> <uniqueKey>id</uniqueKey> <!--fieldType是定义字段类型--> <fieldType name="string" class="solr.StrField" sortMissingLast="true" /> <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/> <!--定义复杂的字段类型,添加中文ik类型,并且需要在lib中引入jar包--> <fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"> </fieldType>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" /> <!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> --> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" /> <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType> </schema> |
ik中文分词器的jar包是存放在Tomcat中部署的solr项目中的lib中
solrconfig.xml
这个配置文件主要用于优化索引库的,处理请求等.
<lib dir="../contrib/extraction/lib" regex=".*\.jar" /> <lib dir="../dist/" regex="solr-cell-\d.*\.jar" />
<lib dir="../contrib/clustering/lib/" regex=".*\.jar" /> <lib dir="../dist/" regex="solr-clustering-\d.*\.jar" />
<lib dir="../contrib/langid/lib/" regex=".*\.jar" /> <lib dir="../dist/" regex="solr-langid-\d.*\.jar" />
<lib dir="../contrib/velocity/lib" regex=".*\.jar" /> <lib dir="../dist/" regex="solr-velocity-\d.*\.jar" /> |
上述是用来查找solr依赖包,扩展插件包,需要找到放置的lib包的constrib和dist文件夹,或者更改路径或者拷贝到正确路径.
<requestHandler name="/select" class="solr.SearchHandler"> <!-- default values for query parameters can be specified, these will be overridden by parameters in the request --> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int> <str name="df">text</str> </lst> </requestHandler> |
标签用来定义处理请求的,这个例子处理的是查询所有.
五:solr数据库导入数据插件安装
第一步:solrconfig.xml,添加导入数据的插件:
<lib dir="../dist/" regex="solr-dataimporthandler-\d.*\.jar" /> <!--配置importhandler--> <requestHandler name="/import" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">db-data-config.xml</str> </lst> </requestHandler> |
第二步添加配置文件db-data-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/solrtest" user="root" password="simplehxb"/> <document> <entity name="item" query="select id,title,price from items"> <field column="id" name="id"/> <field column="title" name="text"/> <field column="price" name="price"/> </entity> </document> </dataConfig> |
第三步:将jar包拷贝到部署在tomacat的solr项目的lib包中
启动Tomact,如果id不是string类型需要在solrconfig.xml中这一段配置
<searchComponent name="elevator" class="solr.QueryElevationComponent" > <!-- pick a fieldType to analyze queries --> <str name="queryFieldType">string</str> <str name="config-file">elevate.xml</str> </searchComponent> |
六,solrJ的使用
创建maven项目并且管理依赖
<dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>4.10.2</version> </dependency> <!-- Solr底层会使用到slf4j日志系统 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.22</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> |
Creat
编写测试类,测试直接添加文档
@Test public void testSolrCreat() throws Exception{ HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1/solr/coreTest"); //加入document SolrInputDocument solrDocument = new SolrInputDocument(); //向文档中添加字段 solrDocument.addField("id", 15L); solrDocument.addField("price", 150000L); solrDocument.addField("text", "努比亚 智能机 超长待机 能砸核桃"); //添加文档 httpSolrServer.add(solrDocument); //提交 httpSolrServer.commit(); } |
但是一般而言,我们在实际的开发中这种直接添加文档的方式显然是不可取的,从数据库查出数据会被框架直接封装成bean,同样solr提供了直接添加bean的方式创建方式,并且可以添加bean的集合方式.
@Test public void testSolrCreatByBean() throws Exception{ //连接到索引库 HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1/solr/coreTest/"); //创建bean Item item = new Item(16L, 200000L, "一加 玫瑰金 超大内存"); httpSolrServer.addBean(item); //提交 httpSolrServer.commit(); } |
Delete
@Test public void testSolrDelete() throws Exception, IOException{ HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1/solr/coreTest/"); //根据id删除 httpSolrServer.deleteById("16");
httpSolrServer.commit(); } |
之所以说solr可怕是在于它的查询方式,同时删除也可以根据查询来删除,此处可以直接参考api,下面介绍强大的solrj的查询
Retrieve
以Document形式返回查询的结果
@Test public void testSolrRetrieveByDocument() throws Exception{ //连接索引库 HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1/solr/coreTest/"); //创建查询条件 SolrQuery query = new SolrQuery("text:手机"); //接受返回结果 QueryResponse response = httpSolrServer.query(query); //拿到文档集合 SolrDocumentList solrDocumentList = response.getResults(); System.out.println("共查到"+solrDocumentList.size()+"条数据"); for (SolrDocument solrDocument : solrDocumentList) { System.out.println("id:"+solrDocument.get("id")); System.out.println("price:"+solrDocument.get("price")); System.out.println("text:"+solrDocument.get("text")); } } |
同样以bean形式返回方式
@Test public void testSolrRetrieveByBean() throws Exception{ //连接索引库 HttpSolrServer httpSolrServer = new HttpSolrServer("http://127.0.0.1/solr/coreTest/"); //创建查询条件 SolrQuery query = new SolrQuery("text:手机"); //接受返回结果 QueryResponse response = httpSolrServer.query(query); //拿到文档集合 List<Item> items = response.getBeans(Item.class); for (Item item : items) { System.out.println(item); } } |
总结:
SolrQuery对象的高级查询
在创建SolrQuery时,我们填写的Query语句,可以有以下高级写法:
查询语句中如果有特殊字符,需要转义,可以使用:””
1、匹配所有文档:*:* (通配符?和*:“*”表示匹配任意字符;“?”表示匹配出现的位置)
2、布尔操作:AND、OR和NOT布尔操作(推荐使用大写,区分普通字段)
3、子表达式查询(子查询):可以使用“()”构造子查询。 比如:(query1 AND query2) OR (query3AND query4)
4、相似度查询:
(1)默认相似度查询:title:appla~ ,此时编辑举例是2
(2)指定编辑举例的相似度查询:对模糊查询可以设置编辑举例,可选0~2的整数。
5、范围查询(Range Query):Lucene支持对数字、日期甚至文本的范围查询。结束的范围可以使用“*”通配符。
(1)日期范围(ISO-8601 时间GMT):a_begin_date:[1990-01-01T00:00:00Z TO 1999-12-31T24:59:99Z]
(2)数字:salary:[2000 TO *]
(3)文本:entryNm:[a TO a]
6、日期匹配:YEAR, MONTH, DAY, DATE (synonymous with DAY) HOUR, MINUTE, SECOND, MILLISECOND, and MILLI (synonymous with MILLISECOND)可以被标志成日期。
(1)r_event_date:[* TO NOW-2YEAR]:2年前的现在这个时间
(2)r_event_date:[* TO NOW/DAY-2YEAR]:2年前前一天的这个时间