我正在尝试将CouchDB用于新的应用程序,我需要创建一个按多个字段排序并按多个字段过滤的视图。这是一个示例文档,我省略了_id和_rev以节省一些打字。
{
"title": "My Document",
"date": 1279816057,
"ranking": 5,
"category": "fun",
"tags": [
"couchdb",
"technology"
],
}
从文档中,我了解到我可以轻松创建一个按排名等字段排序的视图。
function(doc) {
emit(doc.ranking, doc);
}
我还了解到,我可以轻松按类别
等字段进行过滤function(doc) {
emit(doc.category, doc);
}
http://127.0.0.1:5984/database/_design/filter/_view/filter?key=%22fun%22
我的问题是我需要同时做一堆这些事情。我想根据类别和标签进行过滤。我应该能够过滤到只有“fun”类别和“couchdb”标签的文档。我想通过按降序排序,然后按日期按升序排序,然后按字母顺序按标题排序过滤结果。
如何创建一个完成所有排序和过滤的视图?
答案 0 :(得分:47)
要在密钥中发送多个数据,您需要阅读Complex Keys。您最有可能最终emit()
使用由类别和标记组成的数组的键。例如......
function(doc) {
for(var i = 0; i < doc.tags.length; i++)
emit([doc.category, doc.tags[i]], doc);
}
现在,当您查询?key=["fun", "couchdb"]
时,您将获得标记为“couchdb”的有趣类别中的所有项目。或者,如果您想要有趣类别中的所有项目,无论其标记如何,那么您可以使用范围?startkey=["fun"]&endkey=["fun", {}]
进行查询。请记住,如果您的商品有多个标签,您会在结果中多次获取该标签(因为您每个标签emit()
一次该文档)。
要按照评级,日期和标题进行排序,您需要在数组中添加两个元素:整数以及排名,日期或标题。请记住,每个地图功能可以emit()
多次。示例地图功能...
function(doc) {
for(var i = 0; i < doc.tags.length; i++)
{
emit([doc.category, doc.tags[i], 0, doc.ranking], doc);
emit([doc.category, doc.tags[i], 1, doc.title], doc);
emit([doc.category, doc.tags[i], 2, doc.date], doc);
}
}
现在您的关键结构是:["category", "tag", 0 ... 2, rank/title/date]
您基本上将所有排名归类为0,标题低于1,日期低于2.当然,您要传输大量数据,因此您可以将每个分组分解为单独的视图在您的设计文档中,或仅返回文档_id
作为值(emit([ ...], doc._id);
)。
使用“couchdb”标签(升序)获取“有趣”类别中的所有内容:
?startkey=["fun", "couchdb"]&endkey=["fun", "couchdb", {}, {}]
使用“couchdb”标记(降序)获取“有趣”类别中的所有内容:
?startkey=["fun", "couchdb", {}, {}]&endkey=["fun", "couchdb"]&descending=true
使用couchdb标记(升序)获取有趣类别中的排名:
?startkey=["fun", "couchdb", 0]&endkey=["fun", "couchdb", 0, {}]
使用“couchdb”标记(降序)获取“fun”类别中的排名:
?startkey=["fun", "couchdb", 0, {}]&endkey=["fun", "couchdb", 0]&descending=true
我希望这会有所帮助。复杂的键开始真正显示切片和切割数据时Map / Reduce的强大功能。
干杯。