1.索引過程
創建索引,採用的邏輯思路是:使用正則表達式,從nutch抓取流程產生的文件parse_txt中提取不同的內容,建立不同的索引域。該方法的好處是,對於論壇、新聞等不同的採集信息,可以產生不同的索引域。實例如下:
parse_txt文檔格式(以新聞爲例):
http://app.finance.ifeng.com/report/all.php <news><newstitle></newstitle><newstime></newstime><newssource></newssource><newsauthor></newsauthor><newstext>請選擇研究機構
東海證券長江證券宏源證券國元證券國泰君安證券東北證券海通證券廣發證券中金公司中信證券招商證券
</newstext></news>
索引代碼處理:
//新聞文本索引
private NutchDocument addNewsContent(NutchDocument doc,String textString){
String textRegex="<newstext>(.*?)</newstext>";
Pattern p=Pattern.compile(textRegex);
Matcher m=p.matcher(textString.replaceAll("\n", "").replaceAll("\r", ""));
while(m.find()){
doc.add("newscontent", m.group(1));
}
return doc;
}
對於<newsauthor>、<newstitle>則用類似的方法建立相應的索引域。
在對新聞文本建立索引的過程中,出現了一個問題:newscontent索引域中的索引項是空的。出現這個現象的原因是,<newstext>標籤中的文本內容中有\n、\r等符號,這會影響正則的使用。添加了replaceAll("\n", "").replaceAll("\r", "")之後,問題就解決了。(爲何會出現這種情況,還有待研究)。
2.查詢過程
2.1.查詢時報attributeSource。。。。的錯誤。這種錯誤一般是中文分詞的代碼中少了某些變量及其對應的操作方法,google一下,一般比較好解決。
2.2.String index out of range -2,報這個錯誤時,就要求修改summary-basic代碼,如果你用的summary-basic插件的話。如何修改,詳見http://blog.163.com/jiaxizhu@yeah/blog/static/1574538772011111145347369/。問題還是由分詞引起的,具體原因還不太清楚,功力不夠啊!
2.3.修改查詢源碼,實現跨索引庫查詢。
對這段代碼的修改,主要集中在NutchBean的初始化過程中。
將以下這段代碼,進行修改;
final Path luceneConfig = new Path(dir, "search-servers.txt");
final Path solrConfig = new Path(dir, "solr-servers.txt");
final Path segmentConfig = new Path(dir, "segment-servers.txt");
if (fs.exists(luceneConfig) || fs.exists(solrConfig)) {
searchBean = new DistributedSearchBean(conf, luceneConfig, solrConfig);
} else {
final Path indexDir = new Path(dir, "index");
final Path indexesDir = new Path(dir, "indexes");
searchBean = new LuceneSearchBean(conf, indexDir, indexesDir);
}
if (fs.exists(segmentConfig)) {
segmentBean = new DistributedSegmentBean(conf, segmentConfig);
} else if (fs.exists(luceneConfig)) {
segmentBean = new DistributedSegmentBean(conf, luceneConfig);
修改後的代碼如下:
public NutchBean(Configuration conf, Path dir) throws IOException {
this.conf = conf;
this.fs = FileSystem.get(this.conf);
//TODO
String[] dires=null;
if (dir == null) {
dir = new Path(this.conf.get("searcher.dir", "crawl"));
//TODO
dires=dir.toString().split(";");
}
//TODO
Path[] indexCollection=new Path[dires.length];
Path[] indexesCollection=new Path[dires.length];
Path[] segmentsCollection=new Path[dires.length];
Path[] linkdbCollection=new Path[dires.length];
if(dires==null){
System.out.println("search.dir元素中的值沒有被成功操作");
}
else{
for(int i=0;i<dires.length;i++){
dir=new Path(dires[i]);
Path indexDir = new Path(dir, "index");
Path indexesDir = new Path(dir, "indexes");
Path segmentsDir=new Path(dir,"segments");
Path linkdbDir=new Path(dir,"linkdb");
indexCollection[i]=indexDir;
indexesCollection[i]=indexesDir;
segmentsCollection[i]=segmentsDir;
linkdbCollection[i]=linkdbDir;
}
searchBean = new LuceneSearchBean(conf, indexCollection, indexesCollection);
segmentBean = new FetchedSegments(conf, segmentsCollection);
}
// linkDb = new LinkDbInlinks(fs, new Path(dir, "linkdb"), conf);
linkDb = new LinkDbInlinks(fs,linkdbCollection , conf);
}
我們可以知道在初始化NutchBean的過程中,初始化了searchBean以及segmentBean以及linkDb。
相應的,各個類的代碼也要修改。
2.3.1.LuceneSearchBean
該類是用來讀取索引的。爲了滿足多索引讀取的要求,得修改其構造方法,重載一個構造方法:
public LuceneSearchBean(Configuration conf, Path[] indexDir, Path[] indexesDir)
throws IOException {
this.conf = conf;
this.fs = FileSystem.get(this.conf);
init(indexDir, indexesDir);
}
在這個類中,最重要的是在init方法中初始化了IndexSearcher類,該類中則初始化了Lucene的IndexSearcher,實現索引庫的查詢。
對於IndexSearcher,它有兩個重載的構造方法,用於接收多索引路徑與單索引路徑。方法如下:
/** Construct given a number of indexes. */
public IndexSearcher(Path[] indexDirs, Configuration conf) throws IOException {
IndexReader[] readers = new IndexReader[indexDirs.length];
this.conf = conf;
this.fs = FileSystem.get(conf);
for (int i = 0; i < indexDirs.length; i++) {
readers[i] = IndexReader.open(getDirectory(indexDirs[i]));
}
init(new MultiReader(readers), conf);
}
/** Construct given a single merged index. */
public IndexSearcher(Path index, Configuration conf)
throws IOException {
this.conf = conf;
this.fs = FileSystem.get(conf);
init(IndexReader.open(getDirectory(index)), conf);
}