Solr之MoreLikeThis


1,相似匹配

  在网页搜索或电商产品搜索结果页面,很多时候会看到一个相似文档、相似产品或找相似的链接。Solr 使用 MoreLikeThisComponent(MLT)和 MoreLikeThisHandler 实现了一样的功能。如上所述,MLT 是与标准 SolrRequestHandler 集成在一起的;MoreLikeThisHandler 与 MLT 结合在一起,并添加了一些其他选项,但它要求发布一个单一的请求。我将着重讲述 MLT,因为使用它的可能性更大一些。
  MLT 要求字段被储存或使用检索词向量,检索词向量以一种以文档为中心的方式储存信息。MLT 通过文档的内容来计算文档中关键词语,然后使用原始查询词语和这些新词语创建一个新的查询。提交新查询就会返回其他查询结果。所有这些都可以用检索词向量来完成:只需将 termVectors="true" 添加到 schema.xml 中的 声明。

2,MoreLikeThis两种实现

  第一种:SearchHandler中的MoreLikeThisComponent,MoreLikeThis以组件的身份出现,适于简单应用。

  第二种:MoreLikeThisHandler,MoreLikeThis作为一个单独的Handler来处理,可以应用过滤等较复杂操作。

3,参数查询

  id,文档主键,或使用其他唯一键;

  fl,需要返回的字段

  mtl.fl,根据哪些字段判断相似度

  mlt.mindf,最小文档频率,所在文档的个数小于这个值的词将不用于相似判断

  mlt.mintf,最小分词频率,在单个文档中出现频率小于这个值的词将不用于相似判断 mlt.count,返回相似文章个数
  需要注意的是 mlt.fl 中的 field 的 termVectors=true 才有效果。
  

4,第一种solrJ的实现

HttpSolrClient solrServer = SolrServer.getServer();
SolrQuery query = new SolrQuery();
List articles = new ArrayList();
try {
  query.setQuery("id:" + id)
  .setParam("fl", "id,title,brand_s")
  .setParam("mlt", "true")
  .setParam("mlt.fl", "title")
  .setParam("mlt.mindf", "1")
  .setParam("mlt.mintf", "1")
  .setParam("mlt.count", String.valueOf(count));

  QueryResponse response = solrServer.query(query);
  if (response == null)

return articles;

SimpleOrderedMap mltResults = (SimpleOrderedMap) response.getResponse().get("moreLikeThis");
for (int i = 0; i < mltResults.size(); i++) {
  SolrDocumentList items = mltResults.getVal(i);
  for (SolrDocument doc : items) {
    String idStr = doc.getFieldValue("id").toString();
    if (StringUtils.equals(idStr, id)) continue;// 排除本身
    ProductBO article = new ProductBO();
    article.setId(idStr);
    article.setTitle(doc.getFieldValue("title").toString());
    article.setBrand_s(doc.getFieldValue("brand_s").toString());
    articles.add(article);
}
}

5,第二种solrJ实现

  配置MoreLikeThisHandler,修改solrconfig.xml
  在最后一个requestHandler下新增/mlt
  

  SolrQuery query = new SolrQuery();      // 指定配置的RequestHandler,默认使用/select    
   query.setRequestHandler("/mlt");   
   List

articles = new ArrayList
();   
   try {      
       query.setQuery("id:" + id)                .
    setParam("fl", "id,title,score")             
     .setParam("mlt", "true")            
     .setParam("mlt.fl", "title")
    .setParam("mlt.mindf", "1")
    .setParam("mlt.mintf", "1");
  query.addFilterQuery("status:" + Article.STATUS_PUBLISHED);
  query.setRows(count);// mlt.count无效,需要此方法控制返回条数
   QueryResponse response =  solrServer.query(query);
  if (response == null) return articles;