5

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

上下文:首先,有点忏悔:我是一个关于 Solr 的菜鸟。对我来说,设置服务器、定义模式、编写功能索引管理器,然后实际看到服务器返回正确的结果 - 完全符合预期!- 对它自己来说已经是一个很大的成就。耶我!

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

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

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

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

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

在此先感谢,非常抱歉这篇长文!

更新

经过大量阅读 API 和特别是反复试验后,我设法获得了功能性解决方案。但是我仍然无法理解 Solr 的大部分内部结构,因此仍然希望能得到一些启发。随意bash,我还是很清楚我的菜鸟的。

解决方案的相关部分是这个由覆盖的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);

}

4

3 回答 3

2

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

另请参阅http://wiki.apache.org/solr/SolrRequestHandler

于 2011-05-31T03:43:16.757 回答
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);
        }
于 2011-06-02T16:29:06.233 回答
0

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

于 2011-05-31T14:13:09.547 回答