Djapian - 过滤结果

1 投票
2 回答
870 浏览
提问于 2025-04-15 14:38

我在用Djapian通过关键词搜索对象,但我想对结果进行筛选。如果能用Django的QuerySet API来做这件事就好了,比如说:

if query.strip():
    results = Model.indexer.search(query).prefetch()
else:
    results = Model.objects.all()
results = results.filter(somefield__lt=somevalue)
return results

但是Djapian返回的是一组ResultSet对象,这些对象是Hit类型的,而不是Model类型的。当然,我可以在Python里手动筛选这些对象,但如果要筛选所有对象(当查询为空时),这就不太现实了——我得从数据库里把整个表都取出来。

我在用Djapian的时候是不是没戏了?

2 个回答

0

我不太了解Djapian,但我对xapian比较熟悉。在Xapian中,你可以用一个叫做MatchDecider的东西来过滤搜索结果。

这个MatchDecider的决策函数会在每一个符合搜索条件的文档上被调用,所以在这里对每个文档都去数据库查询并不是个好主意。不过,你当然可以访问文档中的值。

举个例子,在ubuntuusers.de网站上,我们有一个xapian数据库,里面存储了博客文章、论坛帖子、行星条目、维基条目等等,每个文档都有一些额外的访问信息作为值存储。在查询之后,一个AuthMatchDecider会过滤出潜在的文档,并返回过滤后的结果集,这些结果会展示给用户。

如果决策过程很简单,比如说某个字段小于某个值,你也可以直接把这个字段的值加到文档的值中(使用xapian提供的sortable_serialize函数),然后在原始查询中添加一个OP_FILTEROP_VALUE_RANGE的查询。

4

我查看了它的源代码,发现Djapian有一个可以用来过滤结果的方法。我刚刚试了下面的代码,似乎可以正常工作。

我的索引器如下:

class MarketIndexer( djapian.Indexer ):

    fields = [ 'name', 'description', 'tags_string', 'state']
    tags = [('state', 'state'),]

这是我过滤结果的方法(第一行是为了处理通配符的,不用在意):

objects = model.indexer.search(q_wc).flags(djapian.resultset.xapian.QueryParser.FLAG_WILDCARD).prefetch()
objects = objects.filter(state=1)

执行后,现在它会返回状态等于“1”的Market

撰写回答