solr全文檢索入門
文章目錄
安裝
從官網下載Solr7.4(或本資源包內直接解壓,本包內也是官網下載的)
下載地址:https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/7.4.0/
因為我是Windows系統所以選的是.zip的版本,如果是Linux系統需要用.tgz的版本,下面都是以Windows系統下的示例。
Solr7.4是免安裝的,解壓後就可以直接使用了。
啟動
開啟之後是這樣的
建立core
在cmd視窗輸入:
solr create -c testcore
testcore 是自己起的名字,回車後會出現下面的資訊(還是會有log4j2的錯誤資訊,不用管)
一重新整理
Core也可以直接在控制檯建立,但是需要自己先再Solr安裝根目錄/server/solr目錄下建立一個core資料夾,而且裡面要自己建立一個data資料夾。然後通過控制檯的Core Admin建立core 。
個人建議直接在cmd視窗用命令建立,省力省心還可靠。
網上還有自己拷貝conf資料夾到自己建立core 等等的操作,感覺太麻煩。有興趣的自行百度。
配置core索引MySQL資料
1、把資料庫驅動jar包放到
Solr安裝根目錄/server/solr-webapp/webapp/WEB-INF/lib下
2、把Solr安裝根目錄/dist資料夾下的
solr-dataimporthandler-x.x.x.jar
solr-dataimporthandler-extras-x.x.x.jar
放到Solr安裝根目錄/server/solr-webapp/webapp/WEB-INF/lib下
4、Solr安裝根目錄/server/solr/核心/conf路徑下新增檔案data-config.xml,並新增以下內容(示範如下)
<dataConfig >
<!-- url如果包含特殊字元如";",必須使用html轉移字元 -->
<dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/solrdb" user="root" password="123456"/>
<document>
<!-- query為全量更新SQL -->
<entity name="testdb" pk="tid" query="select * from testdb">
<!-- 每一個field對映著資料庫中列與文件中的域,column是資料庫列,name是solr的域(必須是在managed-schema檔案中配置過的域才行) -->
<field column="tid" name="idid"/>
<field column="tname" name="TName"/>
<field column="tbirthday" name="TBirthDay"/>
</entity>
</document>
</dataConfig>
---------------------
作者:這個冬天真的冷
來源:CSDN
原文:https://blog.csdn.net/h0713/article/details/82503848
版權宣告:本文為博主原創文章,轉載請附上博文連結!
3.2.1
solr預設使用UTC時間,即與中國時差8小時,所以需要修改配置檔案:
Solr安裝根目錄/bin/solr.in.sh
SOLR_TIMEZONE=”UTC+8”
預設是註釋掉的,找到SOLR_TIMEZONE修改後面的值為UTC+8
注意:如果單純修改solr.in.sh檔案沒有作用,就修改和solr.in.sh同目錄下的solr.cmd檔案,修改其中的set SOLR_TIMEZONE=UTC為set SOLR_TIMEZONE=UTC+8
3.2.2
修改mysql資料庫的表結構,新增一個時間戳欄位,當某行資料發生更新時該欄位自動更新為修改資料的時間,為solr增量新增提供服務(範例如下)
ALTER TABLE testdb ADD last_modified TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT current_timestamp
3.2.3
修改solr/server/solr/核心/conf路徑下新增檔案data-config.xml,並新增增量SQL(示範如下)
就是多添加了deltaQuery部分
<dataConfig>
<!-- url如果包含特殊字元如";",必須使用html轉移字元 -->
<dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/solrdb" user="root" password="123456"/>
<document>
<!-- query為全量更新SQL -->
<entity name="testdb" pk="tid" query="select * from testdb"
deltaQuery="select tid from testdb where last_modified > '${dih.last_index_time}'">
<!-- 每一個field對映著資料庫中列與文件中的域,column是資料庫列,name是solr的域(必須是在managed-schema檔案中配置過的域才行) -->
<field column="tid" name="idid"/>
<field column="tname" name="TName"/>
<field column="tbirthday" name="TBirthDay"/>
</entity>
</document>
</dataConfig>
4、修改solrconfig.xml,新增以下內容
data-config.xml
5、修改managed-schema,新增mysql中需要存入solr的欄位(示範如下)
準備測試效果:
資料庫裡的資料:
注意:當last_modified的值是0000-00-00 00:00:00時會有錯誤,
因為java的時間是從1970年開始的,所以不能翻譯這個時間,導致的結果就是查不到資料。
現在測試全量更新:依次選擇1234
結果是:
測試增量更新,在資料庫新添一條資料
注意:增量更新就是隻更新有變化的資料,不會更新沒有變化的資料。如果增量更新選擇clean會刪除所有的原索引資料,然後只更新有修改過的資料。
正常使用情況下增量更新的clean是不選擇的。這裡為了測試更新方式是增量更新的方式,所以選擇了clean。切忌用在專案中!!!除非你知道會有什麼後果
結果是:
我們看到,之前的兩條資料被刪除了,只有一條新新增的資料。證明增量更新的功能有效。
四、接下來我們配置一個實用的功能:定時更新
因為資料庫的資料可能是動態變化的,為了能和資料庫的資料“及時”同步,所以就有了這個功能。
它可以按設定時間自動更新一次索引
4.1修改testcore目錄下的配置檔案core.properties
name=testcore
config=solrconfig.xml
schema=data-config.xml
dataDir=data
4.2新增實時更新索引相關的jar包:dataimportscheduler-1.2.jar 到
Solr安裝根目錄/server/solr-webapp/webapp/WEB-INF/lib下
還有兩個jar包因為之前已經新增過了就不需要添加了,是
solr-dataimporthandler-x.x.x.jar
solr-dataimporthandler-extras-x.x.x.jar
4.3 修改Solr安裝根目錄/server/solr-webapp/webapp/WEB-INF/web.xml
把這個新增到裡面
org.apache.solr.handler.dataimport.scheduler.ApplicationListener
注意:中間的內容兩邊不要有空格,容易出現不正常現象
4.4新增更新配置檔案:Solr安裝根目錄/server/solr下新建conf資料夾
在資料夾下新建dataimport.properties檔案
#################################################
# #
# dataimport scheduler properties #
# #
#################################################
# to sync or not to sync
# 1 - active; anything else - inactive
syncEnabled=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,resource
syncCores=testcore
# solr server name or IP address
# [defaults to localhost if empty]
server=localhost
# solr server port
# [defaults to 80 if empty]
port=8983
interval=2
# application name/context
# [defaults to current ServletContextListener's context (app) name]
webapp=solr
# URL params [mandatory]
# remainder of URL
params=/dataimport?command=delta-import&clean=false&commit=true
# schedule interval
# number of minutes between two runs
# [defaults to 30 if empty]
# 重做索引的時間間隔,單位分鐘,預設7200,即5天;
# 為空,為0,或者註釋掉:表示永不重做索引
reBuildIndexInterval=7200
# 重做索引的引數
reBuildIndexParams=/dataimport?command=full-import&clean=true&commit=true
# 重做索引時間間隔的計時開始時間,第一次真正執行的時間=reBuildIndexBeginTime+reBuildIndexInterval*60*1000;
# 兩種格式:2012-04-11 03:10:00 或者 03:10:00,後一種會自動補全日期部分為服務啟動時的日期
reBuildIndexBeginTime=03:10:00
測試定時更新
我們先全量更新一下所有資料,然後在資料庫新增一條資料,再等一分鐘直接查詢
更新前
更新後
五、配置中文分詞
solr自帶的幾個分詞器對中文支援並不好,所以需要使用第三方分詞器對中文進行分詞索引。
常用的分詞器有:ansj和ik,前者的效果更好。
注:目前發現ansj分詞器索引內容大小超過65248位元組時,會報異常,目前尚未找到解決辦法
5.1需要的jar包:
ansj_lucene5_plug-5.1.1.2.jar
ansj_seg-5.1.1.jar
ik-analyzer-solr5-5.x.jar
nlp-lang-1.7.2.jar
放到Solr安裝根目錄/server/solr-webapp/webapp/WEB-INF/lib 中
5.2配置放到Solr安裝根目錄/server/solr/testcore/conf下的managed-schema
(還是之前配置的那個)
!
<!-- ik分詞器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" />
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" />
<!-- 如果不做同義詞,可以不配置下面這個Filter -->
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
</analyzer></fieldType>
<!-- ansj分詞器 -->
<fieldType name="text_ansj" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.ansj.lucene.util.AnsjTokenizerFactory" isQuery="false" stopwords="/path/to/stopwords.dic"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.ansj.lucene.util.AnsjTokenizerFactory" stopwords="/path/to/stopwords.dic"/>
</analyzer>
</fieldType>
然後為要索引的欄位新增分詞器,例如
<field name="TName" type="text_ansj" indexed="true" stored="true"/>
測試
成功了!
SolrJ 操作索引的增、刪、查
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import java.io.IOException;
import java.util.Iterator;
public class IndexOperation {
private static final String urlString = "http://localhost:8983/solr/testcore";
private static SolrClient solr = new HttpSolrClient.Builder(urlString).build();
public void addIndexTest(){//新增一個索引
SolrInputDocument doc = new SolrInputDocument();
//預設id為主鍵,當id存在時更新資料,否則新增資料
doc.addField("id", "3");
doc.addField("name", "hello world test");
doc.addField("age", "230");
doc.addField("addr", "1111");
try {
solr.add(doc);
solr.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void deleteIndexTest(String did){
//通過id刪除索引
try {
solr.deleteById(did);
solr.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//通過搜尋條件刪除索引
//solr.deleteByQuery(query);
}
public void selectIndexTest(){// 查詢
SolrQuery query = new SolrQuery();
// *標示多個任意字元,?標示單個任意字元,~模糊搜尋
query.setQuery("*:*"); //全搜尋
// 分頁
query.setStart(0);
query.setRows(10);
QueryResponse queryResponse = null;
try {
queryResponse = solr.query(query);
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
SolrDocumentList docs = queryResponse.getResults();
Iterator<SolrDocument> iter = docs.iterator();
while(iter.hasNext()){
SolrDocument doc = iter.next();
System.out.println(doc.toString());
}
try {
solr.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//測試
public static void main(String[] args){
IndexOperation ion=new IndexOperation();
ion.addIndexTest();
ion.selectIndexTest();
System.out.println("---------------分割線-----------------");
ion.deleteIndexTest("3");
ion.selectIndexTest();
}
}
七、通過SolrJ對MySQL資料庫進行全量更新、增量更新
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
public class LinkMysql {//對資料庫進行的操作,全量更新,增量更新
private CloseableHttpClient httpclient = null;
private CookieStore cookieStore = null;
private final String baseSolrUrl;
/**
* 全量匯入
*/
private static final String FULL_IMPORT = "full-import";
/**
* 增量匯入
*/
private static final String DELTA_IMPORT = "delta-import";
public LinkMysql(String baseSolrUrl) {
if(!baseSolrUrl.endsWith("/")){
baseSolrUrl += "/";
}
this.baseSolrUrl = baseSolrUrl;
}
private synchronized void init(){
if(httpclient == null){
cookieStore = new BasicCookieStore();
httpclient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
}
}
public void fullImport(String coreName) throws IOException {
init();
HttpPost post = getDataImportPost(coreName, FULL_IMPORT);
httpclient.execute(post);
}
public void deltaImport(String coreName) throws IOException {
init();
HttpPost post = getDataImportPost(coreName, DELTA_IMPORT);
httpclient.execute(post);
}
private HttpPost getDataImportPost(String coreName,String command) throws UnsupportedEncodingException{
HttpPost post = new HttpPost(baseSolrUrl + coreName + "/dataimport?indent=on&wt=json&_=" + new Date().getTime());
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("command", command));
params.add(new BasicNameValuePair("verbose", "false"));
if(command.equals(FULL_IMPORT)){
params.add(new BasicNameValuePair("clean", "true"));
}
params.add(new BasicNameValuePair("commit", "true"));
params.add(new BasicNameValuePair("optimize", "false"));
params