On 22/11/2009 11:33 PM, Szymon Kapeniak wrote:
Now I want to retrieve from couchdb list of documents sorted by many
nested keys. What I need at the end is like a python dictionary with
above records as keys, and doc _ids as values. The point is to make it
nest-able with arbitrary order of keys . Ideally this would be all
done by couchdb not client. But I'm not sure if it's possible.

Instead of trying to get all _ids as values, you just let lots of rows come back and merge them client side.


Simplest view can be seen like:

author:
- Tolstoj :  list of  _ids
- Goethe:  list of _ids
- Blake:    list of  _ids

this is easy one, but I need:

author:
- Tolstoj : 1985: list of _ids
               : 1992: list of _ids
- Goethe : ...

Here your map function looks something like:

emit([doc.author, doc.date], null);

Your rows will then be returned, with the _id, in order of author and date. You could query like:

startkey=["Tolstoj", 1985], endkey=["Tolstoj", 1999]

To query a range of dates for a single author.

and even more:

author:
- Tolstoj:  1985: publisher: X: list of _ids
                                          : Y: list of _ids
              :  1992: ...

- Goethe: 1950:

Very similar:

emit([doc.author, doc.date, doc.publisher], null);

By using the group_level capability (see the wiki about the view API), you could still search just by author, by author and date, or by all 3 fields.

and also in reverse:

author:
- Tolstoj:  publisher : X: 1985: list of _ids
                                      :1992: list of _ids

This one would be similar, but would use a different view which changes the order the keys are emitted. Or with some extra tricks you probably could reuse the same view.

Then you should look at the Python 'itertools' module, and specifically the 'groupby' function - this will make it trivial to combine multiple rows with the same key prefix (eg, with the same author) quite easy to work with. Something like:

for author, row_iter in itertools.groupby(rows, lambda r: r['key'][0]):
  print "Author", key, "has the following rows:"
  for row in row_iter:
    print row

Should group all records with the same first key element - ie, the 'author' in the examples above.

HTH,

Mark

Reply via email to