Solr Custom RequestHandler - 注入查询参数

时间:2011-05-31 01:43:43

标签: java solr requesthandler

简短问题: 我正在寻找一种方法(java)拦截对Solr的查询,并注入我的业务逻辑提供的一些额外的过滤参数。我应该使用什么结构?

上下文: 首先,有点坦白:我是Solr的新秀。对我来说,设置服务器,定义模式,编写功能索引管理器,然后实际看到服务器返回正确的结果 - 完全按照预期! - 对自己来说已经是一项成就。我也好!

但是我目前正在从事一个需要更多的企业项目。粗略地说,solr实例将由成千上万的用户通过同一个requestHandler进行查询,即返回的文档会根据用户的权限级别自动过滤。例如,如果用户A和超级用户B都尝试了相同的搜索参数(即使是非常相同的URL),则用户B将获得所有用户A的文件,然后获得更多。为了实现这一目标,文档已经使用必要的权限级别信息编制索引。

好吧,考虑到这一点并利用Solr为newb开发人员提供的大量文档,我试图想出一个简单的自定义requestHandler来覆盖handleRequest函数,以便在SolrQueryRequest中注入必要的额外参数。一切都很好和花花公子 - 除了我在QueryResponse中根本没有看到任何差别,服务器粗鲁地忽略了我的小操作。如果这是最好的方法,在没有太多暗示天气的情况下搜索网络几天后,最终决定在StackOverflow上找到好心人。

所以,简而言之,我的问题是:

  • 这是正确的做法吗?还有其他选择吗?我已经掌握了Solr的一些概念,但不可否认的是,有很多缺乏,而且完全有可能缺少一些东西。

  • 如果是这样,修改查询参数后,我应该做些什么来强制更新QueryResponse?据我所知,这些仅仅是封装http请求,并且在修改完成后我无法嗅探查询服务器的任何内容。

提前致谢,非常抱歉这篇长篇文章!

更新

经过大量的阅读API和特别多的试验和错误后,我设法获得了功能性解决方案。然而,我仍然不了解Solr的内部情况,因此仍然会欣赏一些启发。随意随意打击,我仍然非常清楚我的开玩笑。

解决方案的相关部分是这个函数,它通过覆盖handleRequestBody来调用:

private void SearchDocumentsTypeII(SolrDocumentList results,
        SolrIndexSearcher searcher, String q, 
        UserPermissions up, int ndocs, SolrQueryRequest req,
        Map<String, SchemaField> fields, Set<Integer> alreadyFound)
        throws IOException, ParseException {


         BooleanQuery bq = new BooleanQuery();
         String permLvl = "PermissionLevel:" + up.getPermissionLevel();
         QParser parser = QParser.getParser(permLvl, null, req);
         bq.add(parser.getQuery(), Occur.MUST);

         Filter filter = CachingWrapperFilter(new QueryWrapperFilter(bq));   

         QueryParser qp = new QueryParser(q, new StandardAnalyzer());
         Query query =  qp.parse(q);                        

         append (results, searcher.search(
          query, filter, 50).scoreDocs,
          alreadyFound, fields, new HashMap<String,Object>(), 0,
          searcher.getReader(), true);

}

基本上不会以任何方式修改搜索查询,而是应用包含用户的PermissionLevel的过滤器。即便如此,为什么以下替代方案不起作用?搜索查询在标准requestHandler中应用时效果很好,而在这种情况下,它根本不会遇到任何文档。

private void SearchDocumentsTypeII(SolrDocumentList results,
        SolrIndexSearcher searcher, String q, 
        UserPermissions up, int ndocs, SolrQueryRequest req,
        Map<String, SchemaField> fields, Set<Integer> alreadyFound)
        throws IOException, ParseException {

         String qFiltered = q + " AND " + "PermissionLevel:" + up.getPermissionLevel();                              

         QueryParser qp = new QueryParser(qFiltered, new StandardAnalyzer());
         Query query =  qp.parse(qFiltered);                        

         append (results, searcher.search(
          query, null, 50).scoreDocs,
          alreadyFound, fields, new HashMap<String,Object>(), 0,
          searcher.getReader(), true);

}

3 个答案:

答案 0 :(得分:2)

好消息:您不需要编写任何代码来执行此操作,您只需正确配置Solr即可。超级用户会点击标准请求处理程序,而普通用户会点击另一个配置了invariant的请求处理程序(也是solr.StandardRequestHandler),并且要对其强制执行过滤查询。

另见http://wiki.apache.org/solr/SolrRequestHandler

答案 1 :(得分:1)

好吧,好吧。如前所述,答案对我有用。随意评论或打击!

   private void SearchDocumentsTypeII(SolrDocumentList results,
            SolrIndexSearcher searcher, String q, 
            UserPermissions up, int ndocs, SolrQueryRequest req,
            Map<String, SchemaField> fields, Set<Integer> alreadyFound)
            throws IOException, ParseException {


             BooleanQuery bq = new BooleanQuery();
             String permLvl = "PermissionLevel:" + up.getPermissionLevel();
             QParser parser = QParser.getParser(permLvl, null, req);
             bq.add(parser.getQuery(), Occur.MUST);

             Filter filter = CachingWrapperFilter(new QueryWrapperFilter(bq));   

             QueryParser qp = new QueryParser(q, new StandardAnalyzer());
             Query query =  qp.parse(q);                        

             append (results, searcher.search(
              query, filter, 50).scoreDocs,
              alreadyFound, fields, new HashMap<String,Object>(), 0,
              searcher.getReader(), true);
        }

答案 2 :(得分:0)

看看这个solr wiki页面,它说我们应该首先考虑使用Apache Manifold Framework,如果它不能满足您的需求,那么编写自己的requestHandler