2011-08-24 87 views
3

我目前正在尝试按三个值进行排序。但是,让我们开始与文档结构:CouchDB通过三个索引键查询和过滤

{ 
    _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接口我tryed请求像

HTTP GET xxx/messages?key=[{}, "USERIDGOESHERE02", {}] 

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

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

回答

6

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

什么是数组排序从最小到最大的样子?如果您阅读视图中的所有键,则左侧的值会变化最小;中间值比左侧变化更多;而右侧的值变化最大。换句话说,数组密钥告诉CouchDB,“首要任务是按key[0]排序,如果相等,那么决胜将是key[1];如果那些也相等,那么下一个决胜者是key[2]等等......”

因此,你可能希望你的按键看起来像这样:

[ "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 ], 

要找到sender_B为receiver_1所有消息还公开信息,你需要两个查询,一个用于"receiver_1", null配对,而另一个用于"receiver_1", "sender_B"。你想知道任何日期,所以你需要一个范围与发送者/接收者匹配的行。不幸的是,HTTP POST查询不支持这一点。

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

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

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

[ "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"], 

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

+0

感谢您的回复,我不得不认识到,对于couchDB来说,新手首先应该了解的是,没有任何通配符是@ user787145所说的。我学到的另一件事是,事实上,视图可以从一个起始索引读到给定的结束索引,而不会在创建视图后从列表中过滤掉一些文档。这导致了观点本身必须包括过滤特征的结论。无论如何,似乎你的第三种方法是最适合我的用例。 – sics

5

我想你想要;

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

可以再用

startkey=["USERID1","USERID2"]&endkey=["USERID1","USERID2",{}] 

此查询将返回USERID1按照日期顺序发送到USERID2所有文件。 {}是一个空对象,并且按照CouchDB归类规则,将排序比任何数字或字符串更高,因此此处的范围将保证包含所有可能的日期。

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

+0

谢谢你的回复!因为@JasonSmith的回复更加详细,我决定将他的回答标记为回复 - 但我也喜欢你的回复! – sics