君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理

http://guoyunsky.iteye.com/blog/761308  

最近要使用Solr做分布式搜索,自己一开始也是从网上搜集一些资料照着做.其中发现对Solr分布式搜索有个误区,会导致搜索结果不正确.比如我这里有两个Shand:
  1)http://localhost:8080/solr1.4/core0/
  2)http://localhost:8080/solr1.4/core1/
  
     我要从中找出查询为110排名为前30的数据,于是我用以下URL:
     1. http://localhost:8080/solr1.4/core0/select?q=110&shards=localhost:8080/solr1.4/core0,localhost:8080/solr1.4/core1&shards.rows=30 

       但发现界面上返回的结果只有10条.这里我已经设置了shards.row=30,但为什么会只返回10条呢?于是自己再加了个start参数,URL如下:
      2. 
http://localhost:8080/solr1.4/core0/select?q=110&shards=localhost:8080/solr1.4/core0,localhost:8080/solr1.4/core1&shards.rows=30&shards.start=30 
  发现结果变化了,但条数还是10条.后来跟踪了下源码,才找到原因,URL应该设置成: 

     3.http://localhost:8080/solr1.4/core0/select?q=110&shards=localhost:8080/solr1.4/core0,localhost:8080/solr1.4/core1&shards.rows=60&start=30&rows=30
     其中从排名第30名开始,获得30条结果,也就是获得排名30到60的结果,应该将start和rows设置为start=30&rows=30,而不是shards.start=30&shards.row=30,而Shard里应该设置为shards.start=0&shards.rows=60(shards.start=0可以省略,Solr默认会从0开始),其shards.rows=start+rows.
  

     以上是设置方法,用于分布式搜索获得排名30-60的数据.这里大概讲下原理:
  
     Solr会构造ShardFieldSortedHitQueue去收集从各个Shard查询的结果,该类继承Lucene的PriorityQueue(我模拟了这个类的方法,可以参考我这篇博客:
  
 http://guoyunsky.iteye.com/blog/723963 ),需要指定排序Field(SortField)和大小.而指定SolrField和大小,Solr里面有个自己的类SortSpec去管理,Solr在查询组件QueryComponent初始化的时候会通过start和rows参数来构造SortSpec.而如果URL里没有这两个参数,则Solr会采用默认的,也就是start=0&rows=10,如此导致我一开始查询结果始终只有10条.
     还有个更严重的问题,如果我需要从多个Shard中获得排名30-60的数据,那么我们肯定要获得每个Shard中排名前60的数据,然后合并各个Shard,找到所有Shard排名前60的数据.然后再从结果后面取30条,也就是排名30-60的数据了.所以如果像我一开始那样指定Shards.row=30,那么获得的是每个Shard排名前30的数据而非60.所以在我第二条URL中加上
  Shards.start=30所获取的结果跟第一条不一样,因为它是让每个Shard取的排名前60的数据.
  
     但发现Solr里面还是有些没注意的地方,比如solrconfig.xml中可以设置<queryResultWindowSize>20</queryResultWindowSize>表示显示结果条数.所以Solr应该采用这个默认值
  而不是它自己定义的10,同时也包括Solr Web管理界面,里面的rows都是设置的10.

posted on 2012-08-02 20:56  刺猬的温驯  阅读(361)  评论(0编辑  收藏  举报