環(huán)境搭建
1、到apache下載solr,地址:http://mirrors.hust.edu.cn/apache/lucene/solr/
2、解壓到某個目錄
3、cd into D:/Solr/solr-4.10.3/example
4、Execute the server by “java -jar startup.jar”Solr會自動運行在自帶的Jetty上
5、訪問http://localhost:8983/solr/#/
PS:solr-5.0 以上默認對schema的管理是使用managed-schema,不能手動修改,需要使用Schema Restful的API操作。如果要想手動修改配置,把managed-schema拷貝一份修改為schema.xml,在solrconfig.xml中修改如下:
<!-- <schemaFactory class="ManagedIndexSchemaFactory"> <bool name="mutable">true</bool> <str name="managedSchemaResourceName">managed-schema</str> </schemaFactory> --> <!-- <PRocessor class="solr.AddSchemaFieldsUpdateProcessorFactory"> <str name="defaultFieldType">strings</str> <lst name="typeMapping"> <str name="valueClass">java.lang.Boolean</str> <str name="fieldType">booleans</str> </lst> <lst name="typeMapping"> <str name="valueClass">java.util.Date</str> <str name="fieldType">tdates</str> </lst> <lst name="typeMapping"> <str name="valueClass">java.lang.Long</str> <str name="valueClass">java.lang.Integer</str> <str name="fieldType">tlongs</str> </lst> <lst name="typeMapping"> <str name="valueClass">java.lang.Number</str> <str name="fieldType">tdoubles</str> </lst> </processor> --> <schemaFactory class="ClassicIndexSchemaFactory"/>
創(chuàng)建MySQL數(shù)據(jù)
DataBase Name: mybatis
Table Name: user
Db.sql

SET FOREIGN_KEY_CHECKS=0;-- ------------------------------ Table structure for `user`-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(50) DEFAULT NULL, `userAge` int(11) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES ('1', 'summer', '30', 'shanghai');INSERT INTO `user` VALUES ('2', 'test1', '22', 'suzhou');INSERT INTO `user` VALUES ('3', 'test1', '29', 'some place');INSERT INTO `user` VALUES ('4', 'lu', '28', 'some place');INSERT INTO `user` VALUES ('5', 'xiaoxun', '27', 'nanjing');View Code使用DataImportHandler導(dǎo)入并索引數(shù)據(jù)
1) 配置D:/Solr/solr-4.10.3/example/solr/collection1/conf/solrconfig.xml
在<requestHandler name="/select" class="solr.SearchHandler">前面上加上一個dataimport的處理的Handler
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler>
2) 在同目錄下添加data-config.xml
<?xml version="1.0" encoding="UTF-8"?><dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/mybatis" user="root" passWord="luxx" batchSize="-1" /> <document name="testDoc"> <entity name="user" pk="id" query="select * from user"> <field column="id" name="id"/> <field column="userName" name="userName"/> <field column="userAge" name="userAge"/> <field column="userAddress" name="userAddress"/> </entity> </document></dataConfig>
說明:
dataSource是數(shù)據(jù)庫數(shù)據(jù)源。
Entity就是一張表對應(yīng)的實體,pk是主鍵,query是查詢語句。
Field對應(yīng)一個字段,column是數(shù)據(jù)庫里的column名,后面的name屬性對應(yīng)著Solr的Filed的名字。
3) 修改同目錄下的schema.xml,這是Solr對數(shù)據(jù)庫里的數(shù)據(jù)進行索引的模式
(1)保留_version_ 這個field
(2)添加索引字段:這里每個field的name要和data-config.xml里的entity的field的name一樣,一一對應(yīng)。
<field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false" /><!--<field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false"/> --><field name="userName" type="text_general" indexed="true" stored="true" /><field name="userAge" type="int" indexed="true" stored="true" /><field name="userAddress" type="text_general" indexed="true" stored="true" />
(3)刪除多余的field,刪除copyField里的設(shè)置,這些用不上。注意:text這個field不能刪除,否則Solr啟動失敗。
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
(4)設(shè)置唯一主鍵:<uniqueKey>id</uniqueKey>,注意:Solr中索引的主鍵默認是只支持type="string"字符串類型的,而我的數(shù)據(jù)庫中id是int型的,會有問題,解決方法:修改同目錄下的elevate.xml,注釋掉下面2行,這貌似是Solr的Bug,原因不明。
<doc id="MA147LL/A" /><doc id="IW-02" exclude="true" />
4)拷貝mysql-connector-java-5.1.22-bin.jar和solr-dataimporthandler-4.10.3.jar到D:/Solr/solr-4.10.3/example/solr-webapp/webapp/WEB-INF/lib。一個是mysql的java驅(qū)動,另一個在D:/Solr/solr-4.10.3/dist目錄里,是org.apache.solr.handler.dataimport.DataImportHandler所在的jar。
重啟Solr。
如果配置正確就可以啟動成功。
solrconfig.xml是solr的基礎(chǔ)文件,里面配置了各種web請求處理器、請求響應(yīng)處理器、日志、緩存等。
schema.xml配置映射了各種數(shù)據(jù)類型的索引方案。分詞器的配置、索引文檔中包含的字段也在此配置。
索引測試
進入Solr主頁,在Core Selector中選擇collection1:http://localhost:8983/solr/#/collection1
點擊Dataimport,Command選擇full-import(默認),點擊“Execute”,Refresh Status就可以看到結(jié)果:
Indexing completed. Added/Updated: 7 documents.Deleted 0 documents.
Requests: 1, Fetched: 7, Skipped: 0, Processed: 7
Started: 8 minutes ago
Query測試:在q中輸入userName:test1進行檢索就可以看到結(jié)果。
這里使用full-import索引了配置數(shù)據(jù)庫中的全部數(shù)據(jù),使用Solr可以查詢對應(yīng)的數(shù)據(jù)。
使用Solrj索引并檢索數(shù)據(jù)
上面是使用Solr Admin頁面上的功能測試索引和檢索,也可以使用代碼來操作Solr,下面的代碼測試了在Solr索引中添加了一個User類實體,并通過查找所有的index來返回結(jié)果。
User實體類:
package com.mybatis.test.model;import org.apache.solr.client.solrj.beans.Field;public class User { @Field private int id; @Field private String userName; @Field private int userAge; @Field private String userAddress; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getUserAge() { return userAge; } public void setUserAge(int userAge) { this.userAge = userAge; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } @Override public String toString() { return this.userName + " " + this.userAge + " " + this.userAddress; }}使用@Field注解的屬性要和Solr配置的Field對應(yīng)。
測試代碼:
package com.solr.test;import java.io.IOException;import org.apache.solr.client.solrj.SolrQuery;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.client.solrj.response.UpdateResponse;import org.apache.solr.common.SolrDocumentList;import com.mybatis.test.model.User;public class SolrTest { private static SolrServer server; private static final String DEFAULT_URL = "http://localhost:8983/solr/collection1"; public static void init() { server = new HttpSolrServer(DEFAULT_URL); } public static void indexUser(User user){ try { //添加user bean到索引庫 try { UpdateResponse response = server.addBean(user); server.commit(); System.out.println(response.getStatus()); } catch (IOException e) { e.printStackTrace(); } } catch (SolrServerException e) { e.printStackTrace(); } } //測試添加一個新的bean實例到索引 public static void testIndexUser(){ User user = new User(); user.setId(8); user.setUserAddress("place"); user.setUserName("cdebcdccga"); user.setUserAge(83); indexUser(user); } public static void testQueryAll() { SolrQuery params = new SolrQuery(); // 查詢關(guān)鍵詞,*:*代表所有屬性、所有值,即所有index params.set("q", "*:*"); // 分頁,start=0就是從0開始,rows=5當(dāng)前返回5條記錄,第二頁就是變化start這個值為5就可以了。 params.set("start", 0); params.set("rows", Integer.MAX_VALUE); // 排序,如果按照id排序,那么將score desc 改成 id desc(or asc) // params.set("sort", "score desc"); params.set("sort", "id asc"); // 返回信息*為全部,這里是全部加上score,如果不加下面就不能使用score params.set("fl", "*,score"); QueryResponse response = null; try { response = server.query(params); } catch (SolrServerException e) { e.printStackTrace(); } if(response!=null){ System.out.println("Search Results: "); SolrDocumentList list = response.getResults(); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } } public static void main(String[] args) { init(); //testIndexUser(); testQueryAll(); }}如果在數(shù)據(jù)庫中添加一條數(shù)據(jù),但是Solr索引中沒有index這條數(shù)據(jù),就查不到,所以一般在使用Solr檢索數(shù)據(jù)庫里的內(nèi)容時,都是先插入數(shù)據(jù)庫,再在Solr中index這條數(shù)據(jù),使用Solr的模糊查詢或是分詞功能來檢索數(shù)據(jù)庫里的內(nèi)容。
DIH增量從MYSQL數(shù)據(jù)庫導(dǎo)入數(shù)據(jù)已經(jīng)學(xué)會了如何全量導(dǎo)入MySQL的數(shù)據(jù),全量導(dǎo)入在數(shù)據(jù)量大的時候代價非常大,一般來說都會適用增量的方式來導(dǎo)入數(shù)據(jù),下面介紹如何增量導(dǎo)入MYSQL數(shù)據(jù)庫中的數(shù)據(jù),以及如何設(shè)置定時來做。
1)數(shù)據(jù)庫表的更改
前面已經(jīng)創(chuàng)建好了一個User的表,這里為了能夠進行增量導(dǎo)入,需要新增一個字段updateTime,類型為timestamp,默認值為CURRENT_TIMESTAMP。
有了這樣一個字段,Solr才能判斷增量導(dǎo)入的時候,哪些數(shù)據(jù)是新的。
因為Solr本身有一個默認值last_index_time,記錄最后一次做full import或者是delta import(增量導(dǎo)入)的時間,這個值存儲在文件conf目錄的dataimport.properties文件中。
2)data-config.xml中必要屬性的設(shè)置
transformer 格式轉(zhuǎn)化:HTMLStripTransformer 索引中忽略HTML標(biāo)簽
query:查詢數(shù)據(jù)庫表符合記錄數(shù)據(jù)
deltaQuery:增量索引查詢主鍵ID 注意這個只能返回ID字段
deltaImportQuery:增量索引查詢導(dǎo)入的數(shù)據(jù)
deletedPkQuery:增量索引刪除主鍵ID查詢注意這個只能返回ID字段
有關(guān)“query”,“deltaImportQuery”, “deltaQuery”的解釋,引用官網(wǎng)說明,如下所示:The query gives the data needed to populate fields of the Solr document infull-importThe deltaImportQuery gives the data needed to populate fields when running adelta-importThe deltaQuery gives the primary keys of the current entity which have changessince the last index time
如果需要關(guān)聯(lián)子表查詢,可能需要用到parentDeltaQuery
TheparentDeltaQuery uses the changed rows of the current table (fetched withdeltaQuery) to give the changed rows in theparent table. This is necessarybecause whenever a row in the child table changes, we need to re-generate thedocument whichhas thatfield.
更多說明看DeltaImportHandler的說明文檔。
針對User表,data-config.xml文件的配置內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?><dataConfig> <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/mybatis" user="root" password="luxx" batchSize="-1" /> <document name="testDoc"> <entity name="user" pk="id" query="select * from user" deltaImportQuery="select * from user where id='${dih.delta.id}'" deltaQuery="select id from user where updateTime> '${dataimporter.last_index_time}'"> <field column="id" name="id"/> <field column="userName" name="userName"/> <field column="userAge" name="userAge"/> <field column="userAddress" name="userAddress"/><field column="updateTime" name="updateTime"/> </entity> </document></dataConfig>增量索引的原理是從數(shù)據(jù)庫中根據(jù)deltaQuery指定的SQL語句查詢出所有需要增量導(dǎo)入的數(shù)據(jù)的ID號。
然后根據(jù)deltaImportQuery指定的SQL語句返回所有這些ID的數(shù)據(jù),即為這次增量導(dǎo)入所要處理的數(shù)據(jù)。
核心思想是:通過內(nèi)置變量“${dih.delta.id}”和 “${dataimporter.last_index_time}”來記錄本次要索引的id和最近一次索引的時間。
注意:剛新加上的updateTime字段也要在field屬性中配置,同時也要在schema.xml文件中配置:
<field name="updateTime" type="date" indexed="true" stored="true" />
如果業(yè)務(wù)中還有刪除操作,可以在數(shù)據(jù)庫中加一個isDeleted字段來表明該條數(shù)據(jù)是否已經(jīng)被刪除,這時候Solr在更新index的時候,可以根據(jù)這個字段來更新哪些已經(jīng)刪除了的記錄的索引。
這時候需要在dataConfig.xml中添加:
query="select * from user where isDeleted=0"deltaImportQuery="select * from user where id='${dih.delta.id}'"deltaQuery="select id from user where updateTime> '${dataimporter.last_index_time}' and isDeleted=0"deletedPkQuery="select id from user where isDeleted=1"這時候Solr進行增量索引的時候,就會刪除數(shù)據(jù)庫中isDeleted=1的數(shù)據(jù)的索引。
測試增量導(dǎo)入
如果User表里有數(shù)據(jù),可以先清空以前的測試數(shù)據(jù)(因為加的updateTime沒有值),用我的Mybatis測試程序添加一個User,數(shù)據(jù)庫會以當(dāng)前時間賦值給該字段。在Solr中使用Query查詢所有沒有查詢到該值,使用dataimport?command=delta-import增量導(dǎo)入,再次查詢所有就可以查詢到剛剛插入到MySQL的值。
設(shè)置增量導(dǎo)入為定時執(zhí)行的任務(wù)
可以用Windows計劃任務(wù),或者linux的Cron來定期訪問增量導(dǎo)入的連接來完成定時增量導(dǎo)入的功能,這其實也是可以的,而且應(yīng)該沒什么問題。
但是更方便,更加與Solr本身集成度高的是利用其自身的定時增量導(dǎo)入功能。
1、下載apache-solr-dataimportscheduler-1.0.jar放到/solr-webapp/webapp/WEB-INF/lib目錄下:下載地址:http://code.google.com/p/solr-dataimport-scheduler/downloads/list也可以到百度云盤下載:http://pan.baidu.com/s/1dDw0MRn
注意:apache-solr-dataimportscheduler-1.0.jar有bug,參考:http://www.denghuafeng.com/post-242.html
2、修改solr的WEB-INF目錄下面的web.xml文件:為<web-app>元素添加一個子元素
<listener> <listener-class> org.apache.solr.handler.dataimport.scheduler.applicationListener </listener-class> </listener>
3、新建配置文件dataimport.properties:
在SOLR_HOME/solr目錄下面新建一個目錄conf(注意不是SOLR_HOME/solr/collection1下面的conf),然后用解壓文件打開apache-solr-dataimportscheduler-1.0.jar文件,將里面的dataimport.properties文件拷貝過來,進行修改,下面是最終我的自動定時更新配置文件內(nèi)容:
################################################## ## dataimport scheduler properties ## ################################################### to sync or not to sync# 1 - active; anything else - inactivesyncEnabled=1# which cores to schedule# in a multi-core environment you can decide which cores you want syncronized# leave empty or comment it out if using single-core deployment# syncCores=game,resourcesyncCores=collection1# solr server name or IP address# [defaults to localhost if empty]server=localhost# solr server port# [defaults to 80 if empty]port=8983# application name/context# [defaults to current ServletContextListener's context (app) name]webapp=solr# URLparams [mandatory]# remainder of URL#http://localhost:8983/solr/collection1/dataimport?command=delta-import&clean=false&commit=trueparams=/dataimport?command=delta-import&clean=false&commit=true# schedule interval# number of minutes between two runs# [defaults to 30 if empty]interval=1# 重做索引的時間間隔,單位分鐘,默認7200,即1天; # 為空,為0,或者注釋掉:表示永不重做索引# reBuildIndexInterval=2# 重做索引的參數(shù)reBuildIndexParams=/dataimport?command=full-import&clean=true&commit=true# 重做索引時間間隔的計時開始時間,第一次真正執(zhí)行的時間=reBuildIndexBeginTime+reBuildIndexInterval*60*1000;# 兩種格式:2012-04-11 03:10:00 或者 03:10:00,后一種會自動補全日期部分為服務(wù)啟動時的日期reBuildIndexBeginTime=03:10:00
這里為了做測試每1分鐘就進行一次增量索引,同時disable了full-import全量索引。
4、測試
在數(shù)據(jù)庫中插入一條數(shù)據(jù),在Solr Query中查詢,剛開始查不到,Solr進行一次增量索引后就可以查詢到了。
一般來說要在你的項目中引入Solr需要考慮以下幾點:1、數(shù)據(jù)更新頻率:每天數(shù)據(jù)增量有多大,及時更新還是定時更新2、數(shù)據(jù)總量:數(shù)據(jù)要保存多長時間3、一致性要求:期望多長時間內(nèi)看到更新的數(shù)據(jù),最長允許多長時間延遲4、數(shù)據(jù)特點:數(shù)據(jù)源包括哪些,平均單條記錄大小5、業(yè)務(wù)特點:有哪些排序要求,檢索條件6、資源復(fù)用:已有的硬件配置是怎樣的,是否有升級計劃
參考:
http://wiki.apache.org/solr/DataImportHandler
http://wiki.apache.org/solr/Solrj
http://www.denghuafeng.com/post-242.html
新聞熱點
疑難解答