CouchDB在同一视图中进行排序和过滤 [英] CouchDB sorting and filtering in the same view
问题描述
{
title:我的文档,
date:1279816057,
ranking:5,
category:fun,
tags
couchdb,
technology
,
}
从文档中,我已经了解到,我可以很容易地创建一个按排序字段进行排序的视图。
function(doc){
emit(doc.ranking,doc);
}
我也了解到, / doc>
function(doc){
emit(doc.category,doc);
}
http://127.0.0.1:5984/database/_design/filter/_view/filter?key=%22fun%22
我的问题是我需要同时完成所有这些事情。我想根据类别和标签进行过滤。我应该能够过滤到只有类别为fun和couchdb标签的文档。我想按降序排列这些筛选结果,然后按升序排列,然后按字母顺序排列。
如何创建一个视图,将所有的排序和筛选功能结合在一起?
为了在一个键中输出多个数据,你需要阅读复杂键。您很可能会最终得到 emit()
'作为由类别和标记组成的数组的键。例如...
function(doc){
。一个示例映射函数...
for(var i = 0; i< doc。 tags.length; i ++)
emit([doc.category,doc.tags [i]],doc);
$ b现在当你查询?key = [fun ,couchdb]
您将获得有趣的类别标记为couchdb的所有项目。或者如果你想要有趣的类别中的所有项目,不管它们的标签是什么,那么你可以用范围来查询:?startkey = [fun]& endkey = [fun,{ }]
。只要记住,如果你的物品有多个标签,你会在结果中多次得到它(因为你的每个标签有一次一次一次的发送(emit()
)。 p>
要按照评分,日期和标题进行额外的排序,您需要在数组中添加两个元素:整数和排名,日期或标题。请记住,您可以在每个地图函数中多次
c发出()
pre $ $ $ $ $ $ $ $ $ $ $ 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] $ b
0以下的排名,1以下的排名和2以下的日期。当然,您正在传输大量的数据,因此您可以将这些分组中的每一个分解到设计文档中的单独视图中,或者只返回doc
_id
作为值(emit([...],doc._id);
)。
使用couchdb标签获取fun类别中的所有内容(升序):
?startkey = [fun,couchdb]& endkey = [fun,couchdb,{},{}]
/ pre>
使用couchdb标记(降序)获取fun类别中的所有内容:
<$ p startkey = [fun,couchdb,{},{}]和endkey = [fun,couchdb]& descending = true
/ code>
使用couchdb标签(升序)获取有趣类别的排名:
?startkey = [fun,couchdb,0]& endkey = [fun,couchdb,0,{}]
/ b>
获得couchdb标签的fun类别中的排名(降序):
?startkey = [fun,couchdb,0,{}]和endkey = [fun,couchdb,0]& descending = true
我希望这有帮助。复杂的键开始真正显示Map / Reduce在切片和切块数据方面的功能。
干杯。
I'm trying to use CouchDB for a new app, and I need to create a view that sorts by multiple fields and also filters by multiple fields. Here is an example document, I've left out the _id and _rev to save myself some typing.
{ "title": "My Document", "date": 1279816057, "ranking": 5, "category": "fun", "tags": [ "couchdb", "technology" ], }
From the documentation, I've learned that I can easily create a view that sorts by a field such as ranking.
function(doc) { emit(doc.ranking, doc); }
I've also learned that I can easily filter by fields such as category
function(doc) { emit(doc.category, doc); } http://127.0.0.1:5984/database/_design/filter/_view/filter?key=%22fun%22
My problem is that I need to do a bunch of these things all at the same time. I want to filter based on category and also tag. I should be able to filter down to only documents with category of "fun" and tag of "couchdb". I want to sort those filtered results by ranking in descending order, then by date in ascending order, then by title in alphabetical order.
How can I create one view that does all of that sorting and filtering combined?
解决方案For emitting more than one piece of data in a key, you'll want to read up on Complex Keys. You'll most likely end up
emit()
'ing a key that is an array made up of the category and tag. For example...function(doc) { for(var i = 0; i < doc.tags.length; i++) emit([doc.category, doc.tags[i]], doc); }
Now when you query
?key=["fun", "couchdb"]
you'll get all the items in the fun category tagged with "couchdb". Or if you want all of the items in the fun category, regardless of their tag, then you can query with a range:?startkey=["fun"]&endkey=["fun", {}]
. Just remember, if your item has multiple tags, you'll get it multiple times in the results (because youemit()
'd the doc once per tag).To go the extra step of sorting by rating, date, and title you'll add two more elements to your array: an integer and either the ranking, date, or title. Remember, you can
emit()
more than once per map function. An example map function...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); } }
Now your key structure is:
["category", "tag", 0 ... 2, rank/title/date]
You're basically grouping all of the rankings under 0, titles under 1, and dates under 2. Of course, you're transmitting a lot of data, so you could either break each of these groupings out into a separate view in your design document, or only return the doc's
_id
as the value (emit([ ...], doc._id);
).Get everything in the "fun" category with the "couchdb" tag (ascending):
?startkey=["fun", "couchdb"]&endkey=["fun", "couchdb", {}, {}]
Get everything in the "fun" category with the "couchdb" tag (descending):
?startkey=["fun", "couchdb", {}, {}]&endkey=["fun", "couchdb"]&descending=true
Get only rankings in the fun category with the couchdb tag (ascending):
?startkey=["fun", "couchdb", 0]&endkey=["fun", "couchdb", 0, {}]
Get only rankings in the "fun" category with the "couchdb" tag (descending):
?startkey=["fun", "couchdb", 0, {}]&endkey=["fun", "couchdb", 0]&descending=true
I hope this helps. Complex keys start to really show how powerful Map/Reduce is at slicing and dicing data.
Cheers.
这篇关于CouchDB在同一视图中进行排序和过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!