前言
讀博快兩年了蜕便,說起來我的方向是Information Retrieval甘凭,可是自己到現(xiàn)在常用的索引包都不會用瓶籽。這次的目的是索引Reddit post的JSON格式的數(shù)據(jù)的,本來想用Glasgow的Terrier巩趁,因為認識幾個他們組里的學生宗弯,都跟我安利這個脯燃。可是用起來發(fā)現(xiàn)Terrier只針對學術(shù)界常用的TREC的數(shù)據(jù)集做了相應的優(yōu)化和文檔配置說明蒙保。對于其他類型的文檔辕棚,Terrier并沒有完整的說明,著實讓人懵逼追他。
鑒于Lucene強大的開源背景和我著實不想再寫Java代碼的懶惰心理坟募,我決定使用Solr 6.0給文檔建立索引,然后通過python調(diào)用curl進行訪問邑狸。
Solr 6.0 安裝
- 配置好JAVA環(huán)境
- 下載zip包
- 解壓縮
Solr 6.0 使用
這個我必須先吐槽一句懈糯,光是配置schema.xml折騰了我一個星期,真的是讀博智商低啊……下面我把終于搞明白了的流程逐步記錄下來单雾。
Standalone版本的啟動流程
- 首先[這是一個非常好的樣例](Solr Schema.xml Example)
- 進入Solr的解壓文件夾
bin/solr start
啟動單機模式赚哗,此時打開瀏覽器輸入http://localhost:8983/solr/
可以看到相關頁面。
- 建立一個Core硅堆,一個Core對應一個對文檔集合的索引屿储。
bin/solr create -c <core name> -d basic_configs
這里我們默認使用basic_configs.
- 對建立好的索引,我們需要配置schema.xml文件和solrconfig.xml文件渐逃,這兩個文件位于server/<core name>文件夾下面够掠。
- 在solrconfig.xml中將這個core設置為讀取手工配置的schema.xml的模式。
<schemaFactory class = "ClassicIndexSchemaFactory"/>
- 講managed-schema文件名改為schema.xml
- 配置schema.xml茄菊,這一步會在下一節(jié)重點說疯潭。
- 重點,重新讀取core才能啟用新配置
curl "http://localhost:8983/solr/admin/cores?action=RELOAD&core=<core name>"
- 索引文件
bin/post -c <core name> /data/redditData/full_corpus.json
- 在python中查詢
from urllib2 import *
import simplejson
import json
connection = urlopen('http://localhost:8983/solr/reddit_r3d/select?q=title:"French%20Open"%20selftext:"French%20Open"&fl=id,name,title,selftext,created_utc&wt=json')
response = simplejson.load(connection)
print response['response']['numFound'], "documents found."
# Create the output file to store relevant documents
output_folderpath = $PATH + corename
if not os.path.exists(output_folderpath):
os.makedirs(output_folderpath)
# Write relevant document in to the file
if response['response']['numFound'] == 0:
continue
else:
output_filepath = (output_folderpath +
query_id + "_" +
str(response['response']['numFound']) + "_" +
str(kvalue) +
".json")
print output_filepath
with open(output_filepath, "w") as text_file:
for document in response['response']['docs']:
text_file.write(json.dumps(document)+'\n')
Schema.xml的手工配置
- 配置fields說明要進行處理的tags
<field name="_root_" type="string" docValues="false" indexed="true" stored="false"/>
<field name="_text_" type="text_en" multiValued="true" indexed="true" stored="false"/>
<field name="_version_" type="long" indexed="false" stored="false"/>
<field name="author" type="text_general" indexed="false" stored="true"/>
<field name="created_utc" type="tlongs" indexed="true" stored="true"/>
<field name="domain" type="text_general" indexed="true" stored="true"/>
<field name="downs" type="tlongs" indexed="false" stored="true"/>
<field name="edited" type="booleans" indexed="false" stored="true"/>
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="is_self" type="booleans" indexed="false" stored="true"/>
<field name="name" type="text_general" indexed="false" stored="true"/>
<field name="num_comments" type="tlongs" indexed="false" stored="true"/>
<field name="retrieved_on" type="tlongs" indexed="false" stored="true"/>
<field name="score" type="tlongs" indexed="false" stored="true"/>
<field name="selftext" type="text_en" indexed="true" stored="true"/>
<field name="subreddit" type="text_general" indexed="true" stored="true"/>
<field name="subreddit_id" type="text_general" indexed="false" stored="true"/>
<field name="title" type="text_en" indexed="true" stored="true"/>
<field name="ups" type="tlongs" indexed="false" stored="true"/>
<field name="url" type="text_general" indexed="true" stored="true"/>
這里需要說明面殖,對于未知文本格式的文本還是選用text_general比較好竖哩,string可能會報錯
- 配置fieldType說明對應類型的field中的內(nèi)容進行什么樣的操作
<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" />
<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>
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
如上,可以定義index過程中和query過程中的具體處理脊僚,我只在原來的基礎上添加了:
<charFilter class="solr.HTMLStripCharFilterFactory"/>
用于處理掉文本中的HTML格式的符號相叁。
- 配置copyField復制field內(nèi)容到另一個field,用于合并field或?qū)ν籪ield做不同的操作辽幌。這里是把這幾個field合并到_text_一同索引:
<copyField source="title" dest="_text_"/>
<copyField source="selftext" dest="_text_"/>
<copyField source="domain" dest="_text_"/>
<copyField source="subreddit" dest="_text_"/>
<copyField source="url" dest="_text_"/>
- 配置dynamicField用于動態(tài)匹配索引過程中遇到的未定義的field
- 對于不關注的field增淹,可以采用下面方法過濾掉:聲明一個忽略類型ignored,動態(tài)匹配所以沒有被定義的field舶衬。
<dynamicField name="*" type="ignored" multiValued="true" />
<fieldType name="ignored" stored="false" indexed="false" docValues="false" multiValued="true" class="solr.TextField" />
額外說明
- Solr 6.0開始埠通,默認索引采用BM25,很重要逛犹。