我使用Redis
为单词和包含这些单词的文档构建倒排索引系统。
设置非常简单:Redis Sets
其中Set
的键是: i:word ,Set
的值是文件ID 有这个词
让我说我有两套:i:example
和i:result
query - "example result"
将与i:example
和i:result
相交,并返回所有同时包含示例和结果的ID
但我正在寻找的是一种执行(以有效方式)查询的方式,例如:" ex res "。结果集应至少包含查询"示例结果"
中的所有ID我想到的解决方案:
创建大小为2的前缀集:p:ex - contains {"example", "expertise", "ex"...}
。查找运行时间不会有问题 - O(1)
来获取集合,O(n)
检查集合中所有以前缀(n = set.size()
开头)的单词中的元素,但我担心关于增加的尺寸价格。
使用扫描:但我不确定运行时间 - scan 0 match ex*
之类的查询会占用O(n)where n is the number of keys in the db吗?我知道redis速度很快,但它可能不是像" ex machi cont" 这样的查询的优化解决方案。
答案 0 :(得分:2)
通常的方法是你提到的第一种方法,但通常你会选择3个字符长的段。请注意,您需要为每个细分设置一套,即。 i:exa
,i:exam
,i:examp
,i:exampl
,当然还有i:example
。
这自然会占用数据库中的空间(因此建议从3开始而不是2个字符)。可能的调整是保留在i:len(3)集中仅引用i:len(4+)集而不是文档id。这将需要更多的读取操作,但在RAM方面将大大节省。
你应该探索v2.8.9增加了排序集的词典范围。通过调用ZRANGEBYLEX
,您可以获得成员范围(即所有以ex开头的单词)。虽然这在此上下文中可能很有用,但请考虑您也可以创建性地使用已排序集的成员来编码单词及其文档参考。这可以帮助你克服损失"得分(因为所有得分都需要相同的词典顺序才能工作)。例如,假设单词" bed"并且"乞求"在文档1和2中:
ZADD index 0 "beg:1" 0 "bed:2"
最后,这里有一点需要考虑的事情 - 添加后缀搜索(例如,所有以" ample"结尾的内容):https://redislabs.com/blog/how-to-use-redis-at-least-x1000-more-efficiently