CouchDB通过三个索引键查询和过滤

时间:2011-08-24 05:03:05

标签: json couchdb mapreduce

我目前正在尝试按三个值的键排序和排序。但是让我们从文档结构开始:

{
    _id: "DOCIDGOESHERE01",
    type: "MESSAGE",
    date: "2011-08-24 06:49:02",
    author: "USERIDGOESHERE01",
    receiver: ["USERIDGOESHERE02", "USERIDGOESHERE03"],
    message: "ok let's do this"
}

主要目标是向couchDB查询所选用户向特定用户发送的消息,并按日期对其进行排序。有些消息没有任何接收器,表明它们是公开的,任何人都可以阅读。

我目前使用的地图功能如下所示:

function map(doc) {
    if(doc.receiver.lenth==0)
        emit([doc.date, null, doc.author], doc._id);
    else for(var idx in doc.receiver)
        emit([doc.date, doc.receiver[idx], doc.author], doc._id);
}

在查询couchDB HTTP接口时,我尝试了像

这样的请求
HTTP GET xxx/messages?key=[{}, "USERIDGOESHERE02", {}]

HTTP POST xxx/messages
{
    keys: [
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE01"],
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE03"],
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE04"],
    ]
}

但所有这些都没有产生我想要制作的文件清单。你对这个任务有什么建议吗?或者用couchDB构建这样的过滤结果是不可能的? 非常感谢你提前!

2 个答案:

答案 0 :(得分:6)

在一个长的1维列表中,键始终从最小到最高排序。 (我试图在The Parable of CouchDB中直观地描述这个,但不知道我是否成功了!)

数组从最小到最大的排序是什么样的?如果您读取视图中的所有键,则左侧值变化最小;中间值变化大于左边;而且右手价值变化最大。换句话说,数组键告诉CouchDB,“首要任务是按key[0]排序,如果相等,则决胜局将是key[1];如果相等,那么下一个决胜局就是{ {1}}等......“

因此,您可能希望您的密钥看起来像这样:

key[2]

要从sender_B以及公共消息中查找receiver_1的所有消息,您需要两个查询,一个用于[ "receiver_1", null , a_date ], [ "receiver_1", "sender_A", some_date ], [ "receiver_1", "sender_B", another_date ], [ "receiver_2", "sender_A", fourth_date ], [ "receiver_3", "sender_C", fifth_date ], 配对,另一个用于"receiver_1", null。您想知道任何日期,因此您需要与发件人/收件人匹配的范围行。不幸的是,HTTP POST查询不支持此功能。

您可以简单地查询每个选定的发件人(甚至所有发件人同时使用线程或异步编程)。接收方和发送方是已知的,此示例允许从最小值("receiver_1", "sender_B")到最大值(null)的范围,其中包括所有日期。

{}

另一种选择是简化您的密钥并删除日期。

?startkey=["receiver_1",null,null]&endkey=["receiver_1",null,{}]
?startkey=["receiver_1","sender_B",null]&endkey=["receiver_1","sender_B",{}]

现在您可以再次使用HTTP POST API进行查询。消息将按日期返回而不是。这不是很糟糕,您可以在客户端(或[ "receiver_1", null ], [ "receiver_1", "sender_A"], [ "receiver_1", "sender_B"], [ "receiver_2", "sender_A"], [ "receiver_3", "sender_C"], [ "receiver_3", "sender_C"], [ "receiver_3", "sender_C"], [ "receiver_3", "sender_C"], [ "receiver_3", "sender_C"], 函数)对它们进行排序。请记住,即使在我的第一个例子中,日期也没有完全排序。

答案 1 :(得分:5)

我想你想要;

emit([doc.author, doc.receiver[idx], doc.date], null);

然后您可以使用

进行查询
startkey=["USERID1","USERID2"]&endkey=["USERID1","USERID2",{}]

这将按照日期顺序返回USERID1发送给USERID2的所有文档。 {}是一个空对象,根据CouchDB排序规则,排序将高于任何数字或字符串,因此这里的范围保证包括所有可能的日期。

最后,我会注意到CouchDB不支持通配符。