利用SOLR搭建企業(yè)搜索平臺 之一(運行solr)
在網(wǎng)絡上找了很多的關于solr的資料,發(fā)現(xiàn)非常的不全面,即使就是官方的wiki,也是如此!
基于現(xiàn)階段正在研究的solr應 用,陸續(xù)的會分享我的一些經(jīng)驗!
今天要說的是: 怎么跑起來!
1》 首先下載好solr,我用的是 solr1.3,下載地址:
windows版本
http://labs.xiaonei.com/apache-m ... ache-solr-1.3.0.zip linux版本
http://labs.xiaonei.com/apache-m ... ache-solr-1.3.0.tgz 2》準備運行容器,我用的是tomcat6.0.20.如果是玩的話,也可以不用準 備專門的容易,你只需解壓好solr的下載包,找到 example文件夾,然后運行 start.jar。具體指令:java -jar start.jar做應用的時候,不建議采用該方式。該方式內部包含了jetty!
3》有關tomcat的使用,不是本文的重點,如 果你有問題,請參見tomcat的使用。解壓好tomcat,將solr包下面的dist文件夾中的apache-solr-1.3.0.war 拷貝到 tomcat的webapps,并且改名為 solr.war。
4》新建一個 solr-tomcat文件夾,我是把這個文件夾建立在C盤根目錄,你可以采用同樣方式,也可以不這樣,放哪由你決定。建立好該文件夾以后,在把它下面在 建立一個solr文件夾,把solr包里面的example\solr文件夾下面的所有文件放入到 solr里面。
5》最后一步 配置 solr.home,可以有三種方式。
1)基于當前路徑的方式
這種情況需要在c:\solr- tomcat\目錄下去啟動tomcat,Solr查找./solr,因此在啟動時候需要切換到c:\solr-tomcat\
2) 基于環(huán)境變量
windows在環(huán)境變量中建立solr.home,值為c:\solr-tomcat
linux 在當前用戶的環(huán)境變量中(.bash_profile)或在catalina.sh中添加如下環(huán)境變量
export JAVA_OPTS="$JAVA_OPTS -Dsolr.solr.home=/opt/solr-tomcat/solr"
3)基于JNDI
在tomcat的conf文件夾建立Catalina文件夾,然后在Catalina文件夾中在建立 localhost文件夾,在該文件夾下面建立solr.xml,其中內容:
Xml代碼
<Context docBase="c:\tomcat\webapps\solr.war" debug="0" crossContext="true" >
<Environment name="solr/home" type="java.lang.String" value="c:/solr-tomcat/solr" override="true" />
</Context>
問題描述:
個人發(fā)現(xiàn)的一個問題,就是如果配置好JNDI的話,然后在tomcat的bin文件夾下面啟動 tomcat的話,會在tomcat的bin下面建立solr文件夾,這個文件夾中主要存放的索引文件。本來這些東西應該放入c:\solr- tomcat\solr。如果你不想出現(xiàn)這種情況的話,請使用基于當前路徑的方式。
6》打開瀏覽器,請看看能否訪問該服務。如果能夠 訪問,恭喜您跑起來了。
利用SOLR搭建企業(yè)搜索平臺 之二(中文分詞)
這篇文章,主要說的是 怎么在solr中加入中文分詞,參考了一些文章,但是還是花了不少時間才搞出的。可能是大俠們太牛了,所以很多細節(jié)東西都沒有寫出來!但是要指出的是很多 文章都是抄來抄去的!
入正題:
在上面的一個文章中,已經(jīng)使solr跑起來了,在上面的基礎上,加入中文分詞。我 用的是paoding分詞器!
1》請下好paoding分詞器,下載地址:
http://code.google.com/p/paoding/downloads/list , 在這里要非常感謝paoding作者:qieqie
在使用paoding的時候要注意:paoding的dic位置,也就是字典的位 置,有兩種辦法解決:
1) 在系統(tǒng)環(huán)境變量中加入PAODING_DIC_HOME這個變量,值為paoding壓縮包下面的dic的解壓位置。
2)paoding-analysis.jar里面有個paoding-dic-home.properties文件,指定dic也可,但是要重新編譯這 個jar包,我采用的后面一種辦法,只要每次固定好dic位置,部署還不是很不方便,設置環(huán)境變量我比較反感
2》建立文件
Java代碼
package com.yeedoo.slor.tokenizer;
import java.io.Reader;
import java.util.Map;
import net.paoding.analysis.analyzer.PaodingTokenizer;
import net.paoding.analysis.analyzer.TokenCollector;
import net.paoding.analysis.analyzer.impl.MaxWordLengthTokenCollector;
import net.paoding.analysis.analyzer.impl.MostWordsTokenCollector;
import net.paoding.analysis.knife.PaodingMaker;
import org.apache.lucene.analysis.TokenStream;
import org.apache.solr.analysis.BaseTokenizerFactory;
public class ChineseTokenizerFactory extends BaseTokenizerFactory {
/**
* 最多切分 默認模式
*/
public static final String MOST_WORDS_MODE = "most-words";
/**
* 按最大切分
*/
public static final String MAX_WORD_LENGTH_MODE = "max-word-length";
private String mode = null;
public void setMode(String mode) {
if (mode == null || MOST_WORDS_MODE.equalsIgnoreCase(mode) || "default".equalsIgnoreCase(mode)) {
this.mode = MOST_WORDS_MODE;
} else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) {
this.mode = MAX_WORD_LENGTH_MODE;
} else {
throw new IllegalArgumentException("不合法的分析器Mode參數(shù)設置:" + mode);
}
}
@Override
public void init(Map<String,String> args) {
super.init(args);
setMode(args.get("mode").toString());
}
public TokenStream create(Reader input) {
return new PaodingTokenizer(input, PaodingMaker.make(), createTokenCollector());
}
private TokenCollector createTokenCollector() {
if (MOST_WORDS_MODE.equals(mode))
return new MostWordsTokenCollector();
if (MAX_WORD_LENGTH_MODE.equals(mode))
return new MaxWordLengthTokenCollector();
throw new Error("never happened");
}
}
利用SOLR搭建企業(yè)搜索平臺 之三(配置文件)
運行solr是個很簡單的事,如何讓solr高效運行你的項目,這個就不容易了。要考慮的因素太多。這里很重要一個就是對solr的配置要了解。懂得配 置文件每個配置項的含義,這樣操作起來就會如魚得水!
在solr里面主要的就是solr的主目錄下面的 schema.xml,solrConfig.xml,如果你看過前兩篇文章的話,你應該知道solr的主目錄處于什么位置(c:\solr- tomcat\solr\conf\)。
在這個文章中,我們首先來說說這個schema.xml。
schema.xml,這個相當于數(shù)據(jù)表配置文件,它定義了加入索引的數(shù)據(jù)的數(shù)據(jù)類型的。主要包括types、fields和其他的一些缺省設置。
1》首先需要在types結點內定義一個FieldType子結點,包括name,class,positionIncrementGap等等一些參 數(shù),name就是這個FieldType的名稱,class指向org.apache.solr.analysis包里面對應的class名稱,用來定義 這個類型的行為。在FieldType定義的時候最重要的就是定義這個類型的數(shù)據(jù)在建立索引和進行查詢的時候要使用的分析器analyzer,包括分詞和 過濾。在例子中text這個FieldType在定義的時候,在index的analyzer中使用 solr.WhitespaceTokenizerFactory這個分詞包,就是空格分詞,然后使用 solr.StopFilterFactory,solr.WordDelimiterFilterFactory,solr.LowerCaseFilterFactory,solr.EnglishPorterFilterFactory,solr.RemoveDuplicatesTokenFilterFactory 這幾個過濾器。在向索引庫中添加text類型的索引的時候,Solr會首先用空格進行分詞,然后把分詞結果依次使用指定的過濾器進行過濾,最后剩下的結果 才會加入到索引庫中以備查詢。Solr的analysis包并沒有帶支持中文的包,在第二篇文章中詳細講了怎樣添加paoding中文分詞器,詳情請參見
http://lianj-lee.javaeye.com/blog/424474 2》接下來的工作就是在fields結點內定義具體的字段(類似數(shù)據(jù)庫中的字段),就是filed,filed定義包括name,type(為之前定義 過的各種FieldType),indexed(是否被索引),stored(是否被儲存),multiValued(是否有多個值)等等。
例:
Xml代碼
<fields>
<field name="id" type="integer" indexed="true" stored="true" required="true" />
<field name="name" type="text" indexed="true" stored="true" />
<field name="summary" type="text" indexed="true" stored="true" />
<field name="author" type="string" indexed="true" stored="true" />
<field name="date" type="date" indexed="false" stored="true" />
<field name="content" type="text" indexed="true" stored="false" />
<field name="keywords" type="keyword_text" indexed="true" stored="false" multiValued="true" />
<field name="all" type="text" indexed="true" stored="false" multiValued="true"/>
</fields>
field的定義相當重要,有幾個技巧需 注意一下,對可能存在多值得字段盡量設置multiValued屬性為true,避免建索引是拋出錯誤;如果不需要存儲相應字段值,盡量將stored屬 性設為false。
3》建議建立了一個拷貝字段,將所有的全文字段復制到一個字段中,以便進行統(tǒng)一的檢索:
Xml代碼
<field name="all" type="text" indexed="true" stored="false" multiValued="true"/>
并在拷貝字段結點處完成拷貝設置:
Xml代碼 <copyField source="name" dest="all"/>
<copyField source="summary" dest="all"/>
4》除此之外,還可以定義動態(tài)字段,所謂動態(tài)字段就是不用指定具 體的名稱,只要定義字段名稱的規(guī)則,例如定義一個 dynamicField,name 為*_i,定義它的type為text,那么在使用這個字段的時候,任何以_i結尾的字段都被認為是符合這個定義的,例 如:name_i,gender_i,school_i等。
利用SOLR搭建企業(yè)搜索平臺 之四(MultiCore)
Solr Multicore 是 solr 1.3 的新特性。其目的一個solr實例,可以有多個搜索應用。
下面著手來將solr給出的一個example跑出來,在《利用SOLR搭建企業(yè)搜索平臺 之一(運行solr)》這篇文章里面已經(jīng)講了怎樣來運行solr,這篇文章是基于《利用SOLR搭建企業(yè)搜索平臺 之一(運行solr)》,有不明白的請參見
http://lianj-lee.javaeye.com/blog/424383 1》 找到solr下載包中的example文件夾,在它的下面有個multicore文件夾,將這個文件夾下面的所有東西copy到 c:\solr-tomcat\solr下面。
注意:有一個 solr.xml(這只是默認文件,當然也可以指定別的文件),如:
Xml代碼
<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="false">
<cores adminPath="/admin/cores">
<core name="core0" instanceDir="core0" />
<core name="core1" instanceDir="core1" />
</cores>
</solr>
這個文件是告訴solr應該加載哪些core,cores里有 core0,core1。core0(可以類比以前的solr.home)/conf目錄下有schema.xml與solrconfig.xml,可以 把實際應用的復制過來。現(xiàn)示例就用官方的了。
2》啟動tomcat,訪問應用,就可以看到有 Admin core0 和 Admin core1
3》采用上面的默認solr.xml,索引文件將存放在同一個目錄下面,在這里將存放在C:\solr- tomcat\solr\data,如果你想更改目錄,或者兩個應用存放在不同的目錄,請參見下面的xml。
Xml代碼
<core name="core0" instanceDir="core0">
<property name="dataDir" value="/data/core0" />
</core>
給core添加子元素 property,property的兩個屬性就不說了,一看就能明白!
solr.core.name -- The core's name as defined in solr.xml
solr.core.instanceDir -- The core's instance directory (i.e. the directory under which that core's conf/ and data/ directory are located)
solr.core.dataDir -- The core's data directory (i.e. the directory under which that core's index directory are located)
solr.core.configName -- The name of the core's config file (solrconfig.xml by default)
solr.core.schemaName -- The name of the core's schema file (schema.xml by default)
4》solr.xml具體含義:
1)solr
The <solr> tag accepts two attributes:
persistent - By default, should runtime core manipulation be saved in solr.xml so that it is available after a restart.
sharedLib - Path to a directory containing .jar files that are added to the classpath of every core. The path is relative to solr.home (where solr.xml sits)
2)cores
The <cores> tag accepts two attribute:
adminPath - Relative path to access the CoreAdminHandler for dynamic core manipulation. For example, adminPath="/admin/cores" configures access via http://localhost:8983/solr/admin/cores . If this attribute is not specified, dynamic manipulation is unavailable. 3)core
The <core> tag accepts two attributes:
name - The registered core name. This will be how the core is accessed.
instanceDir - The solr.home directory for a given core.
dataDir - The data directory for a given core. The default is <instanceDir>/data . It can take an absolute path or a relative path w.r.t instanceDir . Solr1.4
4)property
The <property> tag accepts two attributes:
name - The name of the property
value - The value of the property
由于E文過于 簡單,所以就不翻譯了!
利用SOLR搭建企業(yè)搜索平臺 之五(solrj)
相信很多人,在準備提交數(shù)據(jù)讓solr建立索引的那刻,很納悶,盡管看了不少網(wǎng)上的一些文章,但是我想依然還是有不少不理解的地方。
比如提交一個xml,采用post方式,盡管有些文章說了可以采用httpclient。但是我那個時候,還不是很理解,當然現(xiàn)在看來其實也沒有什么 了。但是對于一個剛入門solr的初學者,我想講講關于solr1.3的 solrj( sorlr J 目前使用二進制的格式作為默認的格式。對于solr1.2的用戶通過顯示的設置才能使用XML格式。)!
先上一個例子:
Java代碼
public static final String SOLR_URL = "http://localhost/solr/core0 "; public static void commit() {
Date date = new Date();
SolrServer solr = null;
try {
solr = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
SolrInputDocument sid = new SolrInputDocument();
sid.addField("id", i);
sid.addField("name", "struts+hibernate+spring 開發(fā)大全" + i);
sid.addField("summary", "三種框架 的綜合應用" + i);
sid.addField("author", "李良杰" + i);
sid.addField("date", new Date());
sid.addField("content", "高級應用類書 籍" + i);
sid.addField("keywords", "SSH" + i);
try {
solr.add(sid);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(i);
if (i == 999)
System.out.println((new Date().getTime() - date.getTime()) / 60000 + "分鐘");
}
try {
solr.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
上面這段代碼的意思是:利用for提交10000 個document,并打印提交10000所需的時間。
1》CommonsHttpSolrServer 使用HTTPClient 和solr服務器進行通信。
2》CommonsHttpSorlrServer 允許設置鏈接屬性。
Java 代碼
server.setSoTimeout(1000); // socket read timeout
server.setConnectionTimeout(100);
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
server.setFollowRedirects(false); // defaults to false
// allowCompression defaults to false.
// Server side must support gzip or deflate for this to have any effect.
server.setAllowCompression(true);
server.setMaxRetries(1); // defaults to 0. > 1 not recommended.
3》實現(xiàn)SolrServer接口的另一個 類:EmbeddedSorrServer,它不需要http連接。
4》在構造document的時候,可以一個一個添加到 solrServer,也可以構建一個包含document的Collection,將Collection添加到solrServer,然后 commit。
5》也可以構造一個跟document匹配的JavaBean進行提交
使用 java 注釋創(chuàng)建java bean。@Field ,可以被用在域上,或者是setter方法上。如果一個域的名稱跟bean的名稱是不一樣的,那么在java注釋中填寫別名,具體的,可以參照下面的域 categories
Java代碼
import org.apache.solr.client.solrj.beans.Field;
public class Item {
@Field
String id;
@Field("cat")
String[] categories;
@Field
List<String> features;
}
java注釋也可以使用在setter方法上,如 下面的例子:
Java代碼
@Field("cat")
public void setCategory(String[] c){
this.categories = c;
}
這里應該要有一個相對的,get方法(沒有加java注釋的)來讀取屬性
Java代碼
Item item = new Item();
item.id = "one";
item.categories = new String[] { "aaa", "bbb", "ccc" };
添加給solr
Java代碼
server.addBean(item);
將多個bean提交給solr
Java代碼
List<Item> beans ;
//add Item objects to the list
server.addBeans(beans);
注意: 你可以重復使用SolrServer,這樣可以提高性能。
6》
Java代碼
public static void update() {
SolrServer solrServer = null;
try {
solrServer = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
UpdateRequest updateRequest = new UpdateRequest();
SolrInputDocument sid = new SolrInputDocument();
sid.addField("id", 100000);
sid.addField("name", "struts+hibernate+spring 開發(fā)大全");
sid.addField("summary", "三種框架的綜合應用");
sid.addField("author", "李良 杰");
sid.addField("date", new Date());
sid.addField("content", "高級應用類書籍");
sid.addField("keywords", "SSH");
updateRequest.setAction(UpdateRequest.ACTION.COMMIT, false, false);
updateRequest.add(sid);
try {
UpdateResponse updateResponse = updateRequest.process(solrServer);
System.out.println(updateResponse.getStatus());
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
提交一個document,采用更新方式,注意:
Java代碼
updateRequest.setAction(UpdateRequest.ACTION.COMMIT, false, false);
7》
Java代碼
public static void query() {
SolrServer solr = null;
try {
solr = new CommonsHttpSolrServer(SOLR_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
return;
}
// http://localhost:8983/solr/spellCheckCompRH?q=epod&spellcheck=on&spellcheck.build=true ModifiableSolrParams params = new ModifiableSolrParams();
params.set("qt", "/spellCheckCompRH");
params.set("q", "編程");
params.set("spellcheck", "on");
params.set("spellcheck.build", "true");
QueryResponse response = null;
try {
response = solr.query(params);
} catch (SolrServerException e) {
e.printStackTrace();
return;
}
System.out.println("response = " + response);
}
這是一個查詢方法。關鍵 字:“編程”。關于查詢的關鍵字,請參見slor wiki
http://wiki.apache.org/solr/QueryParametersIndex , 或等待我的博客更新,在后面會有篇文章詳細講這個問題!
8》給solr的索引文件手動進行優(yōu)化,
solr.optimize();
9》solrJ 提供了一組API,來幫助我們創(chuàng)建查詢,下面是一個faceted query的例子。
SolrServer server = getSolrServer();
SolrQuery solrQuery = new SolrQuery().setQuery("ipod").setFacet(true).setFacetMinCount(1).setFacetLimit(8). addFacetField("category").addFacetField("inStock");
QueryResponse rsp = server.query(solrQuery);
所有的 setter/add 方法都是返回它自己本身的實例,所以就像你所看到的一樣,上面的用法是鏈式的。
利用SOLR搭建企業(yè)搜索平臺 之六(solr查詢參數(shù)說明)
在做solr查詢的時候,solr提供了很多參數(shù)來擴展它自身的強大功能!以下是使用頻率最高的一些參 數(shù)!
具體請看:
1.常用
q - 查詢字符串,必須的。查詢語句(類似SQL) 相關詳細的操作還需lucene 的query 語法
fl - 指定返回那些字段內容,用逗號或空格分隔多個。
start - 返回第一條記錄在完整找到結果中的偏移位置,0開始,一般分頁用。
rows - 指定返回結果最多有多少條記錄,配合start來實現(xiàn)分頁。
sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(score desc, price asc)表示先 “score” 降序, 再 “price” 升序,默認是相關性降序。
wt - (writer type)指定輸出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我們,因為默認沒有打開。
fl表示索引顯示那些field(*表示所有field, score 是solr 的一個匹配熱度)
q.op 表示q 中 查詢語句的 各條件的邏輯操作 AND(與) OR(或)
hl 是否高亮
hl.fl 高亮field
hl.snippets 不太清楚(反正是設置高亮3就可以了)
hl.simple.pre 高亮前面的格式
hl.simple.post 高亮后面的格式
facet 是否啟動統(tǒng)計
facet.field 統(tǒng)計field
fq - (filter query)過慮查詢,作用:在q查詢符合結果中同時是fq查詢符合的,例如:q=mm&fq=date_time:[20081001 TO 20091031],找關鍵字mm,并且date_time是20081001到20091031之間的。官方文檔:
http://wiki.apache.org/solr/Comm ... ec487758577506d6002 2.不常用
q.op - 覆蓋schema.xml的defaultOperator(有空格時用"AND"還是用"OR"操作邏輯),一般默認指定
df - 默認的查詢字段,一般默認指定
qt - (query type)指定那個類型來處理查詢請求,一般不用指定,默認是standard。
3.其它
indent - 返回的結果是否縮進,默認關閉,用 indent=true|on 開啟,一般調試json,php,phps,ruby輸出才有必要用這個參數(shù)。
version - 查詢語法的版本,建議不使用它,由服務器指定默認值。
利用SOLR搭建企業(yè)搜索平臺 之七(solr使用問題集)
某日,突發(fā)奇想,想寫這么一個博客,希望記錄下所有在solr中使用的毛病。而且我希望廣大的看友們也能 一起來說說你們平時遇到的各種錯誤,這樣大家才能一起更好的進步!
話不多說,進入正題
1》solr 做索引時報 Lock obtain timed out: SingleInstanceLock: write.lock
有個頻繁做索引的 應用,它同時也對外提供搜索服務。大部分是 solr 1.3 的默認配置。solr 做索引,有時候報:
Xml代碼
2009-7-13 9:48:06 org.apache.solr.common.SolrException log
嚴重: org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: SingleInstanceLock: write.lock
at org.apache.lucene.store.Lock.obtain(Lock.java:85)
at org.apache.lucene.index.IndexWriter.init(IndexWriter.java:1140)
at org.apache.lucene.index.IndexWriter.<init> (IndexWriter.java:938)
at org.apache.solr.update.SolrIndexWriter.<init>(SolrIndexWriter.java:116)
...
是寫鎖取不到。但重啟 solr 又可以正常做,主要是運行時間長了就報這個錯了。還是看下配置吧。
看到 solr 1.3 默認的配置是:
Xml代碼
<indexDefaults>
<!-- ... -->
<!--
This option specifies which Lucene LockFactory implementation to use.
single = SingleInstanceLockFactory - suggested for a read-only index
or when there is no possibility of another process trying
to modify the index.
native = NativeFSLockFactory
simple = SimpleFSLockFactory
(For backwards compatibility with Solr 1.2, 'simple' is the default
if not specified.)
-->
<lockType>single</lockType>
</indexDefaults>
默認鎖是 single ,只讀的。solr 1.2 是 simple,把它改回去了,運行了幾天,沒事。
2》lucene & solr optimize 索引后結果與平臺有點關系
昨日做索引的程序重構下,測試 optimize 索引(在原有數(shù)據(jù)基礎上提交索引)時,在開發(fā)的機器(windows)里總是會有兩段索引,要再 optimize 才只是一個索引段,當然不是設置 maxSegments=2。反復運行還是如此,為了說明是否寫的程序有問題,就用 solr 自帶的 post.sh (或 post.jar)提交 optimize。結果還是有兩段,再提交一次optimize 才是一個段。這問題……
舊的程序運行得很正常,看了下它也沒有提交 兩次優(yōu)化。然后把新的程序也放到服務器(linux)上運行,結果是只有一個段。
恩,可以認為是與文件系統(tǒng)有關,optimize 的時候是先新生成一段,然后再刪除舊的索引,windows 可能是這樣在運行期間與文件關聯(lián)著刪除不了舊的。linux 可能是不用(不打開)文件就可以刪除。現(xiàn)只能這樣簡單解釋。
3》換 solr 里的 lucene 包
solr 1.3 發(fā)布的時候,lucene 2.4還沒有正式發(fā)布,其的 lucene 是開發(fā)版,現(xiàn)在lucene 2.4早已發(fā)布,那就換上新的 lucene 吧。
下載 solr 1.3
http://labs.xiaonei.com/apache-m ... ache-solr-1.3.0.zip 和 lucene 2.4
http://labs.xiaonei.com/apache-m ... va/lucene-2.4.0.zip 到目錄如e:/search/,
把 e:/search/apache-solr-1.3/lib 目錄下的 lucene 相關的*.jar刪除:
lucene-analyzers-2.4-dev.jar
lucene-core-2.4-dev.jar
lucene-highlighter-2.4-dev.jar
lucene-memory-2.4-dev.jar
lucene-queries-2.4-dev.jar
lucene-snowball-2.4-dev.jar
lucene-spellchecker-2.4-dev.jar
從 e:/search/lucene-2.4/(或contrib/)目錄下找到對應的放到solr-1.3/lib下
然后構建 solr,到e:/search/apache-solr-1.3目錄,ant dist-war
4》solr q查詢容錯性
當solr接收沒q參數(shù)(或q參數(shù)值為空)請求時,會報錯。報錯十分討厭,對開發(fā)調試時才比較有用,但實際運行環(huán)境報錯就不太好了,java異常可能有 點性能消耗,那干脆就返回正常的結果好了(只是結果里沒有找到的數(shù)據(jù))。
solr 1.3 可以寫個組件去做。判斷到空的時候,加一個q參數(shù),其值為在索引里沒有的數(shù)據(jù)。這樣就可以返回沒有數(shù)據(jù)的結果。
其實這樣實現(xiàn)還是比較 麻煩。可以在 solrconfig.xml的requestHandler里加一個默認參數(shù)。如q=abcdefghijk。配置如下:
Xml代碼
<requestHandler name="standard" class="solr.SearchHandler" default="true">
<lst name="defaults">
<str name="q">abcdefghijk</str>
</lst>
</requestHandler>
這樣的話查詢容錯性比較好, 查詢請求沒有帶q參數(shù)也可,q參數(shù)值為空也可。tomcat不會報錯,還可以返回結果。
利用SOLR搭建企業(yè)搜索平臺 之八(solr 實現(xiàn)去掉重復的搜索結果,打SOLR-236_collapsing.patch補丁
引用Bory.Chan
http://blog.chenlb.com/2009/04/a ... plicate-result.html 打上SOLR-236_collapsing.patch補丁,實現(xiàn) solr 搜索結果折疊、除去重復的搜索結果,可以實現(xiàn)類似google搜索結果的“站內的其它相關信息 ”。solr collapsing patch 是用 hash 某個字段來實現(xiàn)折疊重復結果的。下面我演示下應用這個補丁并搜索試用下。
其實 solr 上已經(jīng)有了這功能的實現(xiàn):solr 1.3 collapse patch, 請看:
https://issues.apache.org/jira/browse/SOLR-236 , 我這里下載是了新的:
https://issues.apache.org/jira/s ... 36_collapsing.patch 。
下載好后就需要打上補丁了,先準備一份源碼在D:/apache-solr- 1.3.0目錄下。沒有可以去下載:http: //archive.apache.org/dist/lucene/solr/1.3.0/apache-solr-1.3.0.zip。把SOLR- 236_collapsing.patch文件放在D:/apache-solr-1.3.0目錄下, 打補丁有我知道的有兩種:用linux工具 patch(windows 下有 cygwin);用 ant 的 patch。
windows cygwin 的 patch:
Html代碼
D:\apache-solr-1.3.0>patch -p0 < SOLR-236_collapsing.patch
patching file src/test/org/apache/solr/search/TestDocSet.java
patching file src/java/org/apache/solr/search/CollapseFilter.java
patching file src/java/org/apache/solr/search/DocSet.java
patching file src/java/org/apache/solr/search/NegatedDocSet.java
patching file src/java/org/apache/solr/search/SolrIndexSearcher.java
patching file src/java/org/apache/solr/common/params/CollapseParams.java
patching file src/java/org/apache/solr/handler/component/CollapseComponent.java
ant patch,把下面的內容保存為 patch-build.xml 放到 D:\apache-solr-1.3.0 目錄下:
Xml代碼
<?xml version="1.0" encoding="UTF-8"?>
<project name="solr-patch" default="apply-patch" basedir=".">
<target name="apply-patch" description="Apply a patch file. Set -Dpatch.file">
<patch patchfile="${patch.file}" strip="0"/>
</target>
</project>
ant 打補丁:
Html代碼 D:\apache-solr-1.3.0>ant -Dpatch.file=SOLR-236_collapsing.patch -f patch-build.xml
Buildfile: patch-build.xml
apply-patch:
[patch] patching file src/test/org/apache/solr/search/TestDocSet.java
[patch] patching file src/java/org/apache/solr/search/CollapseFilter.java
[patch] patching file src/java/org/apache/solr/search/DocSet.java
[patch] patching file src/java/org/apache/solr/search/NegatedDocSet.java
[patch] patching file src/java/org/apache/solr/search/SolrIndexSearcher.java
[patch] patching file src/java/org/apache/solr/common/params /CollapseParams.java
[patch] patching file src/java/org/apache/solr/handler/component/CollapseComponent.java
BUILD SUCCESSFUL
Total time: 0 seconds
源碼打上了補丁,然后用 ant 構建源碼:
D:\apache-solr-1.3.0>ant dist
在 D:/apache-solr-1.3.0/dist 目錄下可以找到編譯好的 solr 了。然后把 solr 放到 tomcat 中去運行它,把下面的內容保存在 TOMCAT_HOME/conf/Catalina/localhost/solr.xml 文件中:
Xml代碼
<Context docBase="D:\apache-solr-1.3.0\dist\apache-solr-1.3.0.war" reloadable="true" >
<Environment name="solr/home" type="java.lang.String" value="D:\apache-solr-1.3.0\example\solr" override="true" />
</Context>
修改 D:\apache-solr-1.3.0\example\solr\conf\solrconfig.xml 使 solr 可以支持 collapse。
定義搜索組件,在 QueryComponent 附近:
<searchComponent name="collapse" class="org.apache.solr.handler.component.CollapseComponent" />
定義一個 handler 使用上面的搜索組件:
Xml代碼
<requestHandler name="collapse" class="solr.SearchHandler">
<!-- default values for query parameters -->
<lst name="defaults">
<str name="echoParams">explicit</str>
</lst>
<arr name="components">
<str>collapse</str>
<str>debug</str>
</arr>
</requestHandler>
安裝啟動 tomcat,現(xiàn)在提交一些數(shù)據(jù)給它,用官方的示例數(shù)據(jù)就可以了。運行:
Html代碼 D:\apache-solr-1.3.0\example\exampledocs>java -Durl=http://localhost:8080/solr/update -Dcommit=yes -jar post.jar *.xml SimplePostTool: version 1.2
SimplePostTool: WARNING: Make sure your XML documents are encoded in UTF-8, other encodings are not currently supported
SimplePostTool: POSTing files to http://localhost:8080/solr/update .. SimplePostTool: POSTing file hd.xml
SimplePostTool: POSTing file ipod_other.xml
SimplePostTool: POSTing file ipod_video.xml
SimplePostTool: POSTing file mem.xml
SimplePostTool: POSTing file monitor.xml
SimplePostTool: POSTing file monitor2.xml
SimplePostTool: POSTing file mp500.xml
SimplePostTool: POSTing file sd500.xml
SimplePostTool: POSTing file solr.xml
SimplePostTool: POSTing file spellchecker.xml
SimplePostTool: POSTing file utf8-example.xml
SimplePostTool: POSTing file vidcard.xml
SimplePostTool: COMMITting Solr index changes..
http://localhost:8080/solr/admin/stats.jsp 有結果了? 有了。然后開始查詢試試看。 查詢:http://localhost:8080/solr/select/?q=*%3A*&indent=on& qt=collapse&collapse=true&collapse.field=popularity&collapse.threshold=1
結果:
Xml代碼
<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">0</int>
<lst name="params">
<str name="collapse.field">popularity</str>
<str name="fl">id</str>
<str name="collapse.threshold">1</str>
<str name="indent">on</str>
<str name="q">*:*</str& gt;
<str name="qt">collapse</str>
<str name="collapse">true</str>
</lst>
</lst>
<lst name="collapse_counts">
<str name="field">popularity</str>
<lst name="doc">
<int name="SP2514N">4</int>
<int name="F8V7067-APL-KIT">1</int>
<int name="MA147LL/A">1</int>
<int name="TWINX2048-3200PRO">1</int>
<int name="VS1GB400C3">3</int>
<int name="1">10</int>
</lst>
<lst name="count">
<int name="6">4</int>
<int name="1">1</int>
<int name="10">1</int>
<int name="5">1</int>
<int name="7">3</int& gt;
<int name="0">10</int>
</lst>
<str name="debug">HashDocSet(6) Time(ms): 0/0/0/0</str>
</lst>
<result name="response" numFound="6" start="0">
<doc>
<str name="id">SP2514N</str>
</doc>
<doc>
<str name="id">F8V7067-APL-KIT</str>
</doc>
<doc>
<str name="id">MA147LL/A</str>
</doc>
<doc>
<str name="id">TWINX2048-3200PRO</str>
</doc>
<doc>
<str name="id">VS1GB400C3</str>
</doc>
<doc>
<str name="id">1</str>
</doc>
</result>
</response>
可以看到 collapse_counts 相關的輸出:
<lst name="collapse_counts">
<str name="field">popularity</str>
<lst name="doc">
<int name="SP2514N">4</int>
...
</lst>
<lst name="count">
<int name="6">4</int>
<int name="1">1</int>
<int name="10">1</int>
<int name="5">1</int>
<int name="7">3</int>
<int name="0">10</int>
</lst>
<str name="debug">HashDocSet(6) Time(ms): 0/0/0/0</str>
</lst>
上面的 count 下的內容(它的順序是result/doc的順序),表示 popularity=6 相同的結果還有 4 個,與 popularity=1 相同的結果還有 1 個,依此類推。這樣就可以顯示給用戶的界面里提示“相同的其它內容不有N個”。
使用的參數(shù)有:
#啟用 collapse 組件
collapse=true
#用那個 字段來 hash 去除重量內容
collapse.field=popularity
#要結果中可以最多出 現(xiàn)幾個相同的文檔
collapse.threshold=1
當然還有其它參數(shù),請 看:org.apache.solr.common.params.CollapseParams 類。
利用SOLR搭建企業(yè)搜索平臺 之九(solr的查詢語法)
solr的一些查詢語法
1. 首先假設我的數(shù)據(jù)里fields有:name, tel, address 預設的搜尋是name這個字段, 如果要搜尋的數(shù)據(jù)剛好就是 name 這個字段,就不需要指定搜尋字段名稱.
2. 查詢規(guī)則:
如欲查詢特定字段(非預設字段),請在查詢詞前加上該字段名稱加 “:” (不包含”號) 符號,
例如: address:北京市海淀區(qū)上地軟件園 tel:88xxxxx1
1>. q代表query input
2>. version代表solr版本(建議不要變動此變量)
3>. start代表顯示結果從哪一筆結果資料開始,預設為0代表第一筆, rows是說要顯示幾筆數(shù)據(jù),預設為10筆
(因為有時查詢結果 可能有幾百筆,但不需要顯示所有結果,所以預設是從第一筆開始到第十筆)
所以若要顯示第10到30筆就改為:
http: //localhost:8080/solr/select/?indent=on&version=2.2&q=address:北京 市海淀區(qū)上地軟件園+tel:88xxxxx1&version=2.2&start=10&rows= 20&indent=on
(indent代表輸出的xml要不要縮行.預設為開啟 on)
3. 另外,要限定輸出結果的內容可用 “fl=” 加上你要的字段名稱,如以下這個范例:
http: //localhost:8080/solr/select/?indent=on&version=2.2&q=text:北京+ OR+text:億度&start=0&rows=10&fl=name,address,tel
在fl= 之后加上了name,adress,tel
所以結果會如下:
<result name=”response” numFound=”1340″ start=”0″>
<doc>
<str name=”name”>北京億度</str>
<str name=”address”>北京市海淀區(qū)上地軟件園</str>
<str name=”tel”>88xxxxxx1</str>
</doc>
<doc>
<str name=”name”>北京億度</str>
<str name=”address”/>
<str name=”tel”>88xxxxxx1</str>
</doc>
</result>
5. 查詢 name 或 address:直接輸入查詢詞, 如: 億度
送出的內容即為:
name:億度 AND address:海淀
6. 若要搜尋聯(lián)集結果,請在詞與詞間空格或加上大寫 “OR” (不包含”號).
例如: text:海淀 OR text:億度
text:海淀 OR 億度
或
海淀 億度
或
name:億度 OR tel:88xxxxxx1
或
name:億度 tel:88xxxxxx1
5. 若要搜尋交集結果,請在詞與詞間加上大寫 “AND” 或 “+” (不包含”號).
例如: text:海淀 AND 億度
或
+text:海淀 +text:億度
或
name:億度 AND tel:88xxxxxx1
或
name: ( +億度 +海淀)
6. 排除查詢
在要排除的詞前加上 “-” (不包含”號) 號
例如: 海淀 -億度
搜尋結果不會有包含億度的詞的結果在內
7. Group 搜尋
使用 “()” 來包含一個group
如希望搜尋在店名字段內同時有 “臺北”(不包含”號) 及 “火車站”(不包含”號)
8. 增加權重: 如要搜尋 “北京 加油站”(不包含”號) 但因為回傳太多筆資料內有 “中華”(不包含”號) 或 “加油站”(不包含”號) 的結果,
所以想要把有包含 “加油站”(不包含”號)的數(shù)據(jù)往前排,可使用 “^”(不包含”號)符號在后面加上愈增加的權重數(shù),
像是 “2″,則可以這樣做:
北京 加油站^2
會同時搜尋含有北京或加油站的結果,并把加油站這個詞加權所以 搜尋時會先判斷加油站這一個詞在
搜尋結果中的比重,甚至假設一筆數(shù)據(jù)內加油站出現(xiàn)過兩次以上的就更加會有優(yōu)先權.
查詢時在查詢詞后加上 “^” (不包含”號) 再加上權重分數(shù)
例如: 億度 AND “北京”^2
或
億度^2 OR 北京
9. Wildcard 搜尋使用 “*” 符號; 如果輸入 “中國*銀” (不包含”號), 結果會有中國信托商業(yè)銀行, 中國輸出入銀行圖書閱覽室, 中國商銀證券
中國及銀之間可夾任何長短字詞.
利用SOLR搭建企業(yè)搜索平臺 之十(數(shù)據(jù)庫數(shù)據(jù)導入到solr)
solr不可謂是個好東西啊,越往下挖掘,他的各種功能逐漸的展現(xiàn)在我的面前,對于solr的架構 人員,不得不令人佩服啊。
幾天前偶爾看到IBM developmentWorks上面的一片文章,看到了數(shù)據(jù)庫數(shù)據(jù)的導入,以前我一直是這么認為的,像這種導入可以自己去寫程序去導入。
寫程序 可以將數(shù)據(jù)讀出100條,如果你的內存夠大,可以是1000條甚至更多,然后放入Collection中,批量提交至solr。或者讀取數(shù)據(jù)寫入xml文 件中,再將該文件提交到solr等等。但是,在我看到那一篇文章的時候,原來還有這么巧妙的招。
廢話不多說,入正題。
一.首先準備好solr的dataimport功能需要的東西,在solr的下載包中。分別在:
1》Solr- 1.3.0\dist\apache-solr-dataimporthandler-1.3.0.jar
2》 E:\education\search\Solr-1.3.0\example\example-DIH\solr\
3》你是哪種 數(shù)據(jù)庫,提供該數(shù)據(jù)庫的jdbc驅動。
二.如果你還不會運行solr,請參考本人的前幾篇博客。這里要做的是,先把 E:\education\search\Solr-1.3.0 \example\example-DIH\solr\下面的東西拷貝到solr的HOME目錄,然后刪除rss,這個是另外一個功能是導入rss訂閱信 息到solr中,確實很強,這都想到了。將jar文件,實際就兩個拷貝到tomcat的webapps下面的solr的WEB-INF的lib文件夾下 面。
三.更改solr Home目錄下的conf/solrconfig.xml,其實就是提交一個solrRequestHandler,代碼如下:
Xml代碼
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">C:\solr-tomcat\solr\db\conf\db-data-config.xml</str>
</lst>
</requestHandler>
四.將solr Home目錄下面的solrconfig.xml和schema.xml拷貝到db文件夾下面的conf中。
五.修改db\conf \db-data-config.xml
Xml代碼
<dataConfig>
<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/tuitui" user="root" password="mysql"/>
<document name="shop">
<entity name="tuitui_shop" pk="shopId" query="select * from tuitui_shop">
<field column="shopid" name="shopId" />
<field column="shopName" name="shopName" />
<field column="shopUrl" name="shopUrl" />
<field column="keyword" name="keyword" />
<field column="synopsis" name="synopsis" />
<field column="province" name="province" />
<field column="city" name="city" />
<field column="domain" name="domain" />
<field column="address" name="address" />
<field column="coordinate" name="coordinate" />
<field column="shopSspn" name="shopSspn" />
<field column="phone" name="phone" />
<field column="createTime" name="createTime" />
</entity>
</document>
</dataConfig>
其中的意思我做簡單解釋,具體大家可以去看看官方 wiki。
document:一個文檔也就是lucene的document這個沒什么解釋的;
entity:主要針對的是 一個數(shù)據(jù)庫表;
filed:屬性column是數(shù)據(jù)庫的字段,name是filed的名字,即schema中的field name
http://wiki.apache.org/solr/DataImportHandler 我的數(shù)據(jù)庫表結構發(fā)出來:
六.啟動TOMCAT,輸入地址進行導入,導入 分為很多模式:我選用的全部倒入模式。
http://localhost/solr/dataimport?command=full-import 結果:
00C:\solr-tomcat\solr\db\conf\db-data-config.xmlfull-importidle1202009-09-0521:28:08Indexing completed. Added/Updated: 2 documents. Deleted 0documents.2009-09-05 21:28:092009-09-05 21:28:090:0:0.579This responseformat is experimental. It is likely to change in the future.
七.在去查詢你剛才提交的數(shù)據(jù),搞定。
最后 在說說這個功能。上面的例子只不過是很簡單的一個部分。針對solr的MultiCore,通過配置db-data-config.xml也可以實現(xiàn),還 有多表,或者多表關聯(lián)等等操作只要在db-data-config.xml配置清楚都可以進行數(shù)據(jù)的導入。
在solr1.4中還有更多的擴 展功能,這些功能為重建索引提供能很方便的操作。而且,datasource不單單指的是database,可以是xml文件,還可以是來自網(wǎng)絡上的等 等。
利用SOLR搭建企業(yè)搜索平臺 之十一(中文分詞之IK)
在經(jīng)過使用了庖丁以后,這里說說怎么將目前很火很流行的IK集成進SOLR,其實方法真的很簡單,比 paoding方便不少。這里很感謝IK的作者,藍山咖啡,很感謝你為中文分詞做出的貢獻。 作者博客:http://linliangyi2007.javaeye.com
入正題:
1》請先去作者博客參看IK下載地址,主要就是一個IKAnalyzer3.1.1Stable.jar。我這里用的是最新版!
Java代碼 package com.yeedoo.slor.tokenizer;
import java.io.Reader;
import org.apache.lucene.analysis.TokenStream;
import org.apache.solr.analysis.BaseTokenizerFactory;
import org.wltea.analyzer.lucene.IKAnalyzer;
public class ChineseTokenizerFactory extends BaseTokenizerFactory {
@Override
public TokenStream create(Reader reader) {
return new IKAnalyzer().tokenStream("text", reader);
}
}
從代碼 就可以看得出來真的很方便!將它打包放入solr.war中同時還有IK的jar包。如果你不想打包,請去附件下載已經(jīng)打好的包。
2》配置 文件
Xml代碼 <fieldType name="text" class="solr.TextField" positi>
<analyzer type="index">
<tokenizer class="com.yeedoo.slor.tokenizer.ChineseTokenizerFactory" />
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositi />
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" split />
<filter class="solr.LowerCaseFilterFactory" />
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt" />
<filter class="solr.RemoveDuplicatesTokenFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="com.yeedoo.slor.tokenizer.ChineseTokenizerFactory" />
<filter class="solr.SynonymFilterFactory" syn ignoreCase="true" expand="true" />
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" split />
<filter class="solr.LowerCaseFilterFactory" />
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt" />
<filter class="solr.RemoveDuplicatesTokenFilterFactory" />
</analyzer>
</fieldType>