出于学习目的,我正在尝试在Redis中编写一个简单的结构化文档存储。在我的示例应用程序中,我正在索引数百万个看起来有点像下面的文档。
<book id="1234">
<title>Quick Brown Fox</title>
<year>1999</year>
<isbn>309815</isbn>
<author>Fred</author>
</book>
我正在写一个小的查询语言,允许我说YEAR = 1999 AND TITLE="Quick Brown Fox"
(再次,只是为了我的学习,我不在乎我正在重新发明轮子!)这应该返回ID的匹配的文档(在这种情况下为1234
)。 AND
和OR
表达式可以任意嵌套。
对于每个文档,我按如下方式生成密钥
BOOK_TITLE.QUICK_BROWN_FOX = 1234
BOOK_YEAR.1999 = 1234
我正在使用SADD以KEYNAME.VALUE = { REFS }
形式在一系列集合中填充这些文档。
当我进行查询时,我将表达式解析为AST。一个简单的表达式(如YEAR=1999
)直接映射到SMEMBERS命令,该命令可以返回一组匹配的文档。但是,我不确定如何最有效地执行AND和OR部分。
给出如下的查询:
(TITLE=Dental Surgery OR TITLE=DIY Appendectomy)
AND
(YEAR = 1999 AND AUTHOR = FOO)
我目前向Redis提出以下请求以回答这些问题。
-- Stage one generates the intermediate results and returns RANDOM_GENERATED_KEY3
SUNIONSTORE RANDOMLY_GENERATED_KEY1 BOOK_TITLE.DENTAL_SURGERY BOOK_TITLE.DIY_APPENDECTOMY
SINTERSTORE RANDOMLY_GENERATED_KEY2 BOOK_YEAR.1999 BOOK_YEAR.1998
SINTERSTORE RANDOMLY_GENERATED_KEY3 RANDOMLY_GENERATED_KEY1 RANDOMLY_GENERATED_KEY2
-- Retrieving the top level results just requires the last key generated
SMEMBERS RANDOMLY_GENERATED_KEY3
当我遇到AND
时,我会根据这两个子密钥使用SINTERSTORE(类似于OR
,我使用SUNIONSTORE)。我随机生成一个键来存储结果(并设置一个短的TTL,所以我不会用redft填充Redis)。在这一系列命令结束时,返回值是我可以用SMEMBERS检索结果的键。我使用商店功能的原因是我不想将所有匹配的文档引用传回服务器,所以我使用临时密钥将结果存储在Redis实例上,然后只返回匹配的结果结束。
我的问题很简单,这是将Redis用作文档存储的最佳方式吗?
答案 0 :(得分:2)
我正在使用与排序集类似的方法来实现全文索引。整体方法很好,尽管你可以进行一些相当简单的改进。