我正在尝试在CouchDB中创建一个分页索引视图,其中列出了每个找到的第N个文档的doc._id。
我写了下面的map函数,但 pageIndex 变量不能可靠地从1开始 - 实际上它似乎根据发出的值或索引长度任意改变(例如50,55 ,10,25 - 所有都以不同的文件开头,但我似乎得到了正确的文件数量。)
function(doc) {
if (doc.type == 'log') {
if (!pageIndex || pageIndex > 50) {
pageIndex = 1;
emit(doc.timestamp, null);
}
pageIndex++;
}
}
我在这里做错了什么? CouchDB专家将如何构建此视图?
请注意,我不想使用mentioned elsewhere的“startkey + count + 1”方法,因为我希望能够跳转到特定页面或最后一页(用户期望)我希望有一个友好的“?page = 5”URI而不是“?startkey = 348ca1829328edefe3c5b38b3a1f36d1e988084b”,而且我宁愿CouchDB完成这项工作,而不是填补我的应用程序,如果我可以帮助它。
谢谢!
答案 0 :(得分:6)
查看函数(map
和reduce
)纯粹是功能性的。不支持设置全局变量等副作用。 (当您将应用程序移动到BigCouch时,具有任意数据子集的多个独立服务器如何知道pageIndex
是什么?)
因此,答案必须涉及传统的map
函数,可能由时间戳键入。
function(doc) {
if (doc.type == 'log') {
emit(doc.timestamp, null);
}
}
你怎么能得到每50个文件?最简单的方法是添加skip=0
或skip=50
或skip=100
参数。然而,这并不理想(见下文)。
预取每个第50个文档的确切ID的方法是_list
函数,它只输出每第50行。 (实际上,您可以使用Mustache.JS或其他模板库来构建HTML。)
function() {
var ddoc = this,
pageIndex = 0,
row;
send("[");
while(row = getRow()) {
if(pageIndex % 50 == 0) {
send(JSON.stringify(row));
}
pageIndex += 1;
}
send("]");
}
这适用于许多情况,但并不完美。以下是我正在考虑的一些注意事项 - 不一定是止损,但这取决于您的具体情况。
有理由不鼓励漂亮的网址。如果我加载第1页,然后在前50个中插入一堆文档,然后点击第2页,这意味着什么?如果数据变化很大,没有完美的用户体验,用户必须以某种方式感受到数据的变化。
skip
参数和示例_list
函数存在同样的问题:它们无法扩展。使用skip
,您仍然从头开始触摸视图中的每个行:在数据库文件中找到它,从磁盘读取它,然后一遍又一遍地忽略它,逐行行,直到您达到skip
值。对于非常方便的小值,但由于您将页面分组为50个,我必须想象您将拥有数千或更多行。这可能会导致页面浏览速度变慢,因为数据库大部分时间都在转动轮子。
_list
示例存在类似的问题,但是您需要预先加载所有工作,从头到尾运行整个视图,并且(可能)将相关文档ID发送给客户端,以便快速完成跳转页面。但是有成千上万的文档(你把它们称为“日志”,所以我假设你将有一吨),这将是一个非缓慢的查询,不会被缓存。
总而言之,对于小型数据集,您可以使用page=1
,page=2
表单,但随着数据集变大,您将遇到问题。随着BigCouch的发布,CouchDB对日志存储和分析更加出色(如果这就是你正在做的事情),你一定要考虑扩展的高度。