CouchDB在同一视图中进行排序和过滤 [英] CouchDB sorting and filtering in the same view

查看:201
本文介绍了CouchDB在同一视图中进行排序和过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用CouchDB来创建一个新的应用程序,而且我需要创建一个按多个字段进行排序的视图,并且还可以通过多个字段进行筛选。这里是一个示例文档,我省略了_id和_rev来保存自己的一些输入内容。

  {
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 you emit()'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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆