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);
}