1
votes

I'm brand new to CouchDB (and NoSQL in general), and am creating a simple Node.js + express + nano app to get a feel for it. It's a simple collection of books with two fields, 'title' and 'author'.

Example document:

{
   "_id": "1223e03eade70ae11c9a3a20790001a9",
   "_rev": "2-2e54b7aa874059a9180ac357c2c78e99",
   "title": "The Art of War",
   "author": "Sun Tzu"
}

Reduce function:

function(doc) {
  if (doc.title && doc.author) {
    emit(doc.title, doc.author);
  }
}

Since CouchDB sorts by key and supports a 'descending=true' query param, it was easy to implement a filter in the UI to toggle sort order on the title, which is the key in my results set. Here's the UI:

List of books with link to sort title by ascending or descending

But I'm at a complete loss on how to do this for the author field.

I've seen this question, which helped a poster sort by a numeric reduce value, and I've read a blog post that uses a list to also sort by a reduce value, but I've not seen any way to do this on a string value without a reduce.

1
What do you want to do exactly? Do you want to sort the list on author only?Petter
I want to be able to sort by either title or author, preferably toggling between ascending and descending on subsequent clicks.SchattenJager

1 Answers

2
votes

If you want to sort by a particular property, you need to ensure that that property is the key (or, in the case of an array key, the first element in the array).

I would recommend using the sort key as the key, emitting a null value and using include_docs to fetch the full document to allow you to display multiple properties in the UI (this also keeps the deserialized value consistent so you don't need to change how you handle the return value based on sort order).

Your map functions would be as simple as the following.

For sorting by author:

function(doc) {
  if (doc.title && doc.author) {
    emit(doc.author, null);
  }
}

For sorting by title:

function(doc) {
  if (doc.title && doc.author) {
    emit(doc.title, null);
  }
}

Now you just need to change which view you call based on the selected sort order and ensure you use the include_docs=true parameter on your query.

You could also use a single view for this by emitting both at once...

emit(["by_author", doc.author], null);
emit(["by_title", doc.title], null);

... and then using the composite key for your query.