Lucene权限实现 - 简单之美 - 企业应用与站点完美解决方案
1、权限过滤
Lucene的基于关键字的评分机制,适用于基于相关度的过滤和排序。它是基于矢量模型,其中给文档分配一个相应的分数,分数越高相关的文档也越多。然而,应用系统有时因为用户级权限仅需返回相关文档的子集。
过滤的权限问题实际上是查询时将一个布尔过滤器作用于文档的普遍问题的子问题。我们将探讨这种过滤的实现方法。
2、查询改写
上述权限过滤明显的实现方法,就是改写搜索查询为要求某字段包含特定的值。
例如,如果有一个“类别(category)”字段(Field),并假设仅显示历史(history)和科学(science)类的文档,然后对给定的用户查询:
<query>
查询可被改写为:
<query>+category:history+category:science
3、查询过滤器
此种假设对于过滤的字段(Field)可能是不适宜或不可行的(也许由于字段(Field)是易变的和频繁的变化将导致索引的大量修改)。另一方法是通过 实现Filter接口创建一个过滤器,只需实现一个方法,即bits()方法,该方法返回BitSet,包含命中的所有允许文档ID。
在bits()方法中,可使用TermEnum通过Term筛选(速度慢!),或使用FieldCache检索字段的所有值(速度快,但为内存密集型!)。
4、HitCollector + FieldCache
另一个筛选文档(Documents)的方法是使用HitCollector而非Hits对象。在collect()方法以文档(Document)ID和评分(score)作为参数,可以此来判断文档允许访问与否。
使用HitCollector有一个小缺点,Hits类中遍历搜索结果的有用方法都没有公布,但解决方法容易。
5、范例
比方说,你有一个多用户博客程序,并希望让用户搜索全部(默认)博客文章,或允许用户只搜索他发表的博客。博客应用的Lucene模型将每一博客映射为一Document。
使用查询改写方法,可以轻松地为该查询附加搜索(条件)子句:
<query>+author:<authorid>
这将只返回作者的文档。问题解决了。
现在,扩展该示例。假设在应用中存在3种访问角色:管理员(admin),编辑(editor),作家(author)。这些访问角色的权力是递减的,所 以一个编辑(editor)对作者的博客有写(write)权限,但对管理员(admin)的博客无此权限。如何才能让用户只搜索他具有写访问权限的博客 呢?
该查询改写方法可用来为每一文档(Document)添加一个“角色(role)”字段(Field),并现场填入作者角色(role)。假设用户的角色为编辑(editor),那么改写后查询为:
<query>+(role:editor role:writer)
这种方法是有效的,但不是最理想的,因为每次作者的角色会改变,就需要更新他所写所有博客文档(Documents)。
另一种使用查询改写的方法是获得角色为编辑(editor)和作者(writer)的所有用户列表,然后追加到查询后,如下所示:
<query>+(author:1author:2 author:......)
这方法更好,但庞大的或-查询子句对于布尔过滤可能会妨碍搜索性能。
实现该功能的第三种方法是获取期望的用户列表,如同上前一方法,但不是改写查询,而是使用HitCollector + FieldCache的方法,因此只接受所期望的博客。这种方法具有第二种方法的优势但无性能问题。