Json 基于三个索引键的CouchDB查询和过滤

Json 基于三个索引键的CouchDB查询和过滤,json,couchdb,mapreduce,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" } 主要目标是查询c

我目前正在尝试按一个包含三个值的键进行排序。但让我们从文档结构开始:

{
    _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);
}
[ "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   ],
当查询couchDB HTTP接口时,我尝试了如下请求

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

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

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

从最小到最大排序的数组是什么样子的?如果读取视图中的所有关键点,左侧值变化最小;中间值的变化大于左侧值;右边的值变化最大。换句话说,数组键告诉CouchDB,“第一优先级是按
键[0]
排序,如果相等,则断开连接的键将是
键[1]
;如果这些键也相等,则下一个断开连接的键将是
键[2]
,以此类推。”

因此,您可能希望您的密钥如下所示:

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);
}
[ "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   ],
要从发送方_B查找接收方_1的所有消息以及公共消息,您需要两个查询,一个查询
“接收方_1”,null
配对,另一个查询
“接收方_1”,“发送方_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"],
另一个选择是简化密钥并删除日期

?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进行查询。邮件将返回,不按日期排序。这还不错,您可以在客户端对它们进行排序(或使用
\u列表
函数)。请记住,即使在我的第一个例子中,日期也不是完全排序的。

我想你想要

emit([doc.author, doc.receiver[idx], doc.date], null);
然后,您可以使用

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


最后,我要指出CouchDB不支持通配符。

谢谢你的回复,我第一件意识到CouchDB是新来的,正如@user787145所说的,没有任何通配符。我学到的另一件事是,视图可以从一个起始索引读取到给定的结束索引,而无需在创建视图后从列表中过滤出一些文档。这就得出结论,视图本身必须包含过滤特征。无论如何,您的第三种方法似乎最适合我的用例。谢谢您的回复!因为@JasonSmith的回复更为详细,我决定将他的回答标记为回应——但我也喜欢你的回答!