程序的乐趣

乐趣 开源 简洁 -- Enjoy Open Simple -- EOS
构客网首页  博客  论坛

 
  本文的标签
企业 (收录4篇)全文检索 (收录2篇)lucene (收录2篇)过滤 (收录2篇)filter (收录2篇)
  用户信息
 
帐号:  新手必读
密码: 保存密码
 
  分类列表
全部类别(2 篇)
北京2008(2 篇)
  按月归档
2008年-0月(2 篇)
  SOA2007 - SOA实践
我们何时迈向SOA
——SOA在中国的整体发展现状究竟如何?
我们如何迈向SOA
——中国企业如何迈出实施SOA的第一步?
我们应采用何种技术
——SOA国际标准SCA/SDO的具体内涵?
我们还需要何种技能
——SOA将如何改变系统架构设计以及项目管理过程?

Lucene全文检索:扩展Filter实现自定义过滤全文检索结果

发布时间:2008年05月08日 作者:martindpliu

阅读次数:552次 类别:北京2008 永久链接 Trackback 
参加SOA我有话说

采用Lucene建设企业级全文检索系统,通常需要根据用户权限,检索有权限阅读的文档。本文提出扩展Filter的方式自定义过滤全文检索结果,实现权限过滤功能。

 在企业文档管理系统中,通常需要对索引检索结果进行过滤。Lucene有很多内置的过滤器,可以方便进行检索结果过滤: QueryFilter:过滤内容是符合另外一个查询。相当于两个QueryAnd RangFilter:结果必须在一定范围之内。 ChainedFilter:过滤链。几种Filter按照一定的逻辑顺序组合。 CachingWrapperFilter:增加指定过滤器的cache功能。QueryFilter本身自带CacheRangFilter不带。Cache指对相同的IndexSearcher实例有效,在一个IndexSearcher使用了Cahce过滤器后,再另外一个IndexSearcher实例使用,Cache是不起作用的。另,FilterQuery是一种带过滤的查询,效果等同于过滤器,这种查询可用于BooleanQuery中。

有时候根据具体的需求,有些记录对于一些用户是不可见的,此时就要使用过滤器来防止不合法的用户看到不应该看到的记录。如在企业文档管理系统中,通常需要对用户可阅读的文档进行权限校验。

这里使用了Lucene提供的Filter机制,实现自定义的filter ,根据用户的所在部门,对索引库中的文件进行过滤。返回用户拥有阅读权限的文档。

1 .自定义的Filter实现如下:

public class SearchFilesFilter extends Filter {

     //存放当前用户能访问的文件所属的组织ID列表 ,存放orgId值列表

     private String[] permList;

 

     //设置权限参数列表,orgId值传入SearchFilesFilter

    public SearchFilesFilter(String[] permissions) {permList = permissions;    }  

 

    //实现FilterBitSet方法,根据权限校验要求设置BitSet的值,以过滤检索结果

    public BitSet bits(IndexReader reader) throws IOException {

        //构造返回值BitSet, BitSet集合中每一个变量的值为缺省值false

        BitSet bits = new BitSet(reader.maxDoc());     

        //遍历配置权限信息(orgId列表)

        for (int i = 0; i < permList.length; i++) {

            String orgid = permList[i];

            if (orgid != null) {              

                //构造orgid域对应的Term

                Term t = new Term("orgid", orgid);                 

                //获取所有包含该TermDocuments枚举变量 TermDocs

                TermDocs termDocs = reader.termDocs(t);

                //遍历TermDocs枚举变量中其他Document对象

                while (termDocs.next()) {

                    //设置BitSet termDocs.doc() 对应的值为true

                    bits.set(termDocs.doc());

                }

            }

        }

        return bits;

    }

 2. 建立索引时加入权限信息:

在本文档附带的代码中,以下代码展示了如何在索引中加入权限信息。

IndexFilesFilter中,设置了10个组织ID,随机获取其中一个ORGID,写入文件索引中。其代码如下:

    if (doc != null) {

        Field FieldName = new Field("name", file.getName(), Field.Store.YES, Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);

        doc.add(FieldName);            

 

        Field FieldPath = new Field("path", file.getPath(), Field.Store.YES, Field.Index.TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);                        

        doc.add(FieldPath);

 

        doc.add(new Field("modified",DateTools.timeToString(file.lastModified(), DateTools.Resolution.MINUTE),Field.Store.YES, Field.Index.UN_TOKENIZED));       

 

        String[] orgList = new String[10];

        orgList[1]="5117";

        orgList[2]="5097";

        orgList[3]="7115";

        orgList[4]="4453";

        orgList[5]="3897";         

        orgList[6]="1767";

        orgList[7]="2667";

        orgList[8]="9447";

        orgList[9]="8227";

        orgList[0]="3117";

       

        Random r = new java.util.Random();//为演示需要,随机获取组织ORGID

        int k = r.nextInt(10);

        String orgId = orgList[k];

 

        Field FieldOrgId = new Field("orgid", orgId, Field.Store.YES, Field.Index.UN_TOKENIZED,Field.TermVector.WITH_POSITIONS_OFFSETS);

        doc.add(FieldOrgId);     //加入组织信息ORGID

       

        writer.addDocument(doc); //建立索引

    }

 3. 使用自定义Filter实现权限过滤:

     有了前面的Filter和带权限信息的全文索引,我们可以很方便的实现对检索结果的过滤,代码如下:

 

public static void main(String[] args) throws Exception {

        Hits hits = null;

        String queryString = "解决方案";

        Query query = null;

        String indexHome = IndexFiles.INDEX_HOME;

        IndexSearcher searcher = new IndexSearcher(indexHome);

        IndexFiles index = new IndexFiles();

        try {

            QueryParser qp = new QueryParser("body", index.analyzer);

            query = qp.parse(queryString);

            String[] orgList = new String[10];

            orgList[0]="5097"; orgList[1]="5117";

            Filter filter = new SearchFilesFilter(orgList);   //构造自定义Filter对象

            hits = searcher.search(query, filter); //使用自定义Filter对检索结果进行过滤

            // hits = searcher.search(query );

            if (hits.length() > 0) {

                System.out.println("找到:" + hits.length() + " 个结果!");

                for (int i = 0; i < hits.length(); i++) {

                    Document doc = hits.doc(i);

                    System.out.println("** 结果=" + (i+1));

                    System.out.println("score=" + hits.score(i));

                    System.out.println("name=" + doc.get("name"));

                    System.out.println("orgid=" + doc.get("orgid"));

                }

            }

        } catch (ParseException e) {

        }

     这样,就只检索出orgid50975117的文档。


 评论 查看全部评论