(重要)项目整合nutch索引与查询过程记录

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

  }

这个构造函数中的init方法调用Lucene中的IndexSearcher类的初始化方法,构建相应的对象,用来进行对索引的相关操作。
2.3.2.segmentBean
 要实现查询,除了读索引,还要对segments中的内容进行读取,所以,还要配置相应的segments目录.这是在 segmentBean = new FetchedSegments(conf, segmentsCollection);中实现的。
 在这个构造函数中,修改参数,将 Path segmentsDir改为 Path[] segmentsDir,同时将 private final Path segmentsDir;改为 private final Path[] segmentsDir;。此外,还要修改DistributedSearch,改为:
 //TODO
      Path[] segmentsDirs=new Path[]{segmentsDir};

      //final FetchedSegments segments = new FetchedSegments(conf, segmentsDir);
//TODO
      final FetchedSegments segments = new FetchedSegments(conf, segmentsDirs);

2.3.3.linkDb
  
linkDb = new LinkDbInlinks(fs,linkdbCollection , conf);
不太清楚lindDb这个初始化是干嘛用的,不过根据是用来处理方向连接的事实,应该和url连接有关。
除了将path 改为path[]之外,还要将
Path singleDirectory=directory[i];
        readers = MapFileOutputFormat.getReaders
          (fs, new Path(singleDirectory, LinkDb.CURRENT_NAME), getConf());
改为
for(int i=0;i<directory.length;i++){
       Path singleDirectory=directory[i];
        readers = MapFileOutputFormat.getReaders
          (fs, new Path(singleDirectory, LinkDb.CURRENT_NAME), getConf());
        }
但是不太清楚得到的readers是dierctory中最后一个,还是整个directory数组中的?


2.3.4.过程中产生的错误
  在Myeclipse中,对项目的插件的组织是这样的,将编译得到的.class文件,打包成.jar文件,运行程序时,将会调用.jar中的代码。但是,如果编译的.class文件,仍存在于项目的SourceFolder中时,就不会运行.jar中的,默认使用处于sourceFolder中的.class文件。包括Refenced Libraries中的jar文件,如果项目中存在该.jar文件的源码,且处于sourceFolder中,运行程序时,将不会用到.jar中的代码,而是用到源文件中的。如果别人对某个源码进行了修改,并打包成.jar文件,给你使用,而你项目中包含没有修改的源码,这时问题就出现了,程序不会运行修改的源码,结果还是原来的样子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值