friend ,
我是 Lucene 新手...
我成功地创建了一个索引,添加了字段,我可以进行搜索等等。
现在,我在我的数据库中有一个 View ,告诉哪些用户可以查看哪个文档。这个 View 是使用几个复杂的规则创建的,所以我想重用这个 View 。所以我需要在 Lucene 搜索中添加一个过滤器,以删除与查询匹配但用户无权访问的文档。
我现在尝试做的是:
- 将数据库文档 ID 存储在一个字段中。它是一个 Guid,我将它存储为一个字符串。
- 创建一个自定义过滤器,获取当前用户可以访问的所有文档 ID,然后使用 lucene 中的字段进行过滤
我感觉它效率不高...用户可以访问数十万个文档,因此我可能会检索 200 000 个文档 ID,我需要对其进行过滤。
我想我必须缓存一些东西...
这是我写的代码,但它不起作用:使用过滤器时没有返回任何文档(它应该返回 3 个文档)
public class LuceneAuthorisationFilter : Filter
{
public override DocIdSet GetDocIdSet(Lucene.Net.Index.IndexReader reader)
{
List<Guid> ids = this.load(); // Load list of ID from database
OpenBitSet result = new OpenBitSet(reader.MaxDoc);
int[] docs = new int[1];
int[] freq = new int[1];
for (int i = 0; i < ids.Count; i++)
{
Lucene.Net.Index.TermDocs termDocs = reader.TermDocs(new Lucene.Net.Index.Term("EmId", ids.ElementAt(i).ToString()));
int count = termDocs.Read(docs, freq);
if (count == 1)
{
result.FastSet(docs[0]);
}
}
return result;
}
}
你知道哪里出了问题吗?以及如何提高性能?
谢谢
编辑:
上面的代码有效,问题只是 EmId 字段没有被索引。现在我已经改变并且它有效。
现在我想有任何提高性能的技巧
第二次编辑以添加反馈
注:测试环境包含25000个文档,文档访问列表包含50000个id(因为还没有所有文档
索引)
- 使用上面的自定义过滤器:第一次 ~2600ms,下一次缓存过滤器时 2100ms
- 使用 bool 查询过滤器:~4700ms 然后~4000ms
这些都是糟糕的表现……所以我再次搜索了一个找到的“FieldCacheTermsFilter”过滤器。
- 使用 FieldCacheTermsFilter:~600ms 然后~60ms
这是可以接受的表现
PS:我还发现了另一个类似的question
最佳答案
如果没有给出数字/测量值,谈论性能总是很棘手。
话虽这么说,你在表现方面有哪些表现?您的瓶颈是什么(IO/CPU/等),您是否将其与其他方法进行了比较?
您真的需要提高性能吗?关于性能改进的讨论不是关于“感觉”,而是围绕基于证据和改进需求的确凿事实。
现在是你的过滤器
,除非我没有从问题中得到什么,否则我不明白为什么你不能使用 Lucene 中已经内置的东西来完成艰苦的工作。
这是我通常在 Lucene 中处理权限问题的方式,它总是能很好地处理包含数十亿文档的索引。对于要从缓存中清除的项目,我通常使用具有最小年龄的 LRU 类型缓存。
IE:缓存 100 个项目,但如果最近最少使用的项目不超过 15 分钟,则缓存更多。
如果您尝试这样的事情,如果您将它与您的方法进行比较并返回发布一些性能数据,这可能会很有趣。
免责声明:直接在 SO 的 textarea 中编写的代码,与其将其视为已经工作的复制粘贴解决方案,不如将其视为伪代码:
// todo: probably some thread safety
public class AccessFilterFactory
{
private static AccessFilterFactory _instance = new AccessFilterFactory();;
private AccessFilterFactory()
{
}
public AccessFilterFactory Instance
{
get
{
return _instance;
}
}
private Cache<int, Filter> someKindaCache = new Cache<int, Filter> ();
// gets a cached filter if already built, if not it creates one
// caches it and returns it
public Filter GetFilterForUser(int userId)
{
// return from cache if you got it
if(someKindaCache.Exists(userId))
return someKindaCache.Get(userId);
// if not, build and cache it
BooleanQuery filterQuery = new BooleanQuery();
foreach(string id in ids)
{
filterQuery.Add(new TermQuery(new Term("EmId", id)), BooleanClause.Occur.SHOULD);
}
Filter cachingFilter = new CachingWrapperFilter(new QueryWrapperFilter(filterQuery));
someKindaCache.Put(userId, cachingFilter);
return cachingFilter;
}
// removes a new invalid filter from cache (permissions changed)
public void InvalidateFilter(int userId)
{
someKindaCache.Remove(userId);
}
}
关于c# - Lucene.NET 2.9 自定义过滤器添加授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15808533/