在我的应用程序中,我需要对文档进行类似 SQL 的查询。总体情况是,有一个带有分页表的页面,显示某种“类型”的 couchdb 文档。我有大约 15 个可搜索列,例如时间戳、客户名称、美国州、不同的数字字段等。所有这些列都是可排序的,还有一个过滤器表单允许用户按每个字段进行过滤。
更具体的是,下面是一个典型的查询,它是客户设置一些过滤器选项并转到第二页的结果。它是用伪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 更有趣;)为了解决这个问题,我创建了一个具有以下发出行结构的 View :
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 秒左右的时间,显然我需要进一步优化它。我不敢想,几个月后当我的数据集翻倍、三倍等时,它会变得多慢。
好吧,在解释了我所处的情况后,让我提出实际问题。
是否有更好、更自然的方式来实现我的目标,同时又不失去工具的灵活性?
我使用的 View 结构是最佳的吗?在某些时候,我正在考虑使用单独的 map() 函数生成每个字段的值。这将导致 B 树更小,但 View 服务器生成索引的工作量更大。我可以通过这种方式受益吗?
算法中我必须计算大集合的交集以便稍后获得结果切片的部分让我感到困扰。它不是一种可扩展的方法。有谁知道更好的算法吗?
最佳答案
具有 map 功能:
function(doc){
if(doc.marked_as_test) return;
emit([doc.dataspace, doc.timestamp, doc.fico], null):
}
您可以提出类似的请求:
http://localhost:5984/db/_design/ddoc/_view/view?startkey=["production", :this_weeks_monday_epoch]&endkey=["production", :last_weeks_monday_epoch, 650]&descending=true&limit=15&skip=15
但是,您应该从客户端传递 :this_weeks_monday_epoch
和 :last_weeks_monday_epoch
值(我相信它们是数据库端的一些可计算变量,对吧?)
如果您不关心dataspace
字段(例如它始终是常量),您可以将其移至 map 函数代码中,而不是将其放在查询参数中。
关于sql - 组织复杂的 couchdb View (类似 sql 的查询)的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18310192/