在我的应用程序中,我需要对文档进行类似 SQL 的查询。大图是有一个带有分页表的页面,显示了某种“类型”的 couchdb 文档。我有大约 15 个可搜索的列,例如时间戳、客户名称、美国状态、不同的数字字段等。所有这些列都是可排序的,还有一个过滤器表单允许用户按每个字段进行过滤。
下面更具体的是一个典型的查询,它是客户设置一些过滤器选项并进入第二页的结果。它用pseodo-sql代码编写,只是为了解释问题:
timestamp > last_weeks_monday_epoch AND timestamp < this_weeks_monday_epoch AND marked_as_test = False AND dataspace="production" AND fico > 650
SORT BY timestamp DESC
LIMIT 15
SKIP 15
如果我使用任何类似 sql 的数据库,这将是一个微不足道的问题,但 couchdb 更有趣;)为了解决这个问题,我创建了一个具有以下发射行结构的视图:
key: [field, value], id: doc._id, value: null
现在,要解决上面的示例查询,我需要执行一堆查询:
{startkey: ["timestamp", last_weeks_monday_epoch], endkey: ["timestamp", this_weeks_monday_epoch]}
,*_epoch
这里是整数纪元时间戳,{key: ["marked_as_test", False]}
,{key: ["dataspace", "production"]}
,{startkey: ["fico", 650], endkey: ["fico", {}]}
一旦获得上述查询的结果,我就会计算文档 ID 集的交集,并使用时间戳查询的结果应用排序。最后,我可以应用切片解析第 15-30 行的文档 ID,并使用批量获取操作下载它们的内容。
不用说,它不是最快的操作。目前我正在使用的数据集大约有 10K 个文档。我已经可以看到计算集合交集的部分可能需要 4 秒,显然我需要进一步优化它。我不敢想,当我的数据集翻倍、三倍等时,几个月后它会变得多慢。
好的,在解释了我所处的情况之后,让我问一些实际的问题。
有没有更好、更自然的方法可以在不失去工具灵活性的情况下实现我的目标?
我使用的视图结构是最优的吗?在某些时候,我正在考虑使用单独的 map() 函数来生成每个字段的值。这将导致 b 树更小,但视图服务器生成索引的工作量更大。我可以这样受益吗?
我必须计算大集合的交集以便稍后获得结果切片的算法部分困扰着我。它不是一种可扩展的方法。有谁知道更好的算法吗?