couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Markus Wolff <mar...@wolff-hamburg.de>
Subject Brain check on CouchDB views
Date Sat, 07 Nov 2009 18:25:33 GMT
Hi List,

just to confirm that my brain is not completely dead, I'd like to check
with the experts if I've gotten the concepts right.

Say, I want to build an application that has users and tags. Very
original, I know, nobody ever did that before :-P

Now I need the following functionality:

- Display a global tag cloud with weighted tags of all users
- Display a tag cloud for each user with just the weighted tags
  of that user
- Display a list of documents by user "A", having tag "X"
- Display a list of documents by any user, having tag "X"
- Display a list of documents by any user, having tag "B" AND "Y"!

>>From what I understand, I can achieve almost all of these
functionalities with just two views.

Given that a document looks like this:

{ _id: "some_id", user: "A", tags: ["X","Y","Z"] }

...for the main "by_user" view, my map function would look something
like this:

function(doc) {
  if (doc.tags && doc.tags.length > 0) {
    doc.tags.forEach(function(tag) {
      emit([doc.user,tag], 1);
    });
  }
}

...and my reduce function something like this:

function (keys, values) {
  return sum(values);
}

At first, I experimented a fair bit with fancy rereduce magic, never
getting the results I wanted, until I discovered that I could achieve
nearly all I needed just by applying smarter query parameters:

- Display a tag cloud for each user with just the weighted tags
  of that user

  by_user?group=true&startkey=["A"]&endkey=["A",{}]
  
- Display a list of documents by user "A", having tag "X"

  by_user?reduce=false&startkey=["A", "X"]&endkey=["A","X"]

Now, for the functionalities applying to all users instead of individual
ones, I would have to make a second view (let's call that
"global_tags"). The reduce function could be the same as in the
"by_user" view, just the map function would be very slightly different
(emit only the tag as key, ignore the user):

function(doc) {
  if (doc.tags && doc.tags.length > 0) {
    doc.tags.forEach(function(tag) {
      emit(tag, 1);
    });
  }
}
 
Now I could resolve most of the remaining functionality like this:
 
- Display a global tag cloud with weighted tags of all users

  global_tags?group=true

- Display a list of documents by any user, having tag "X"

  global_tags?reduce=false&startkey="X"&endkey="X"  

The only unresolved feature remaining being querying for tags with
boolean conditions:

- Display a list of documents by any user, having tag "B" AND "Y"!

>>From what I can see, this cannot be resolved with a simple CouchDB view
(except if the condition was OR and the tags were directly adjacent in
the sorting order, but that should be a rare coincidence). Instead, I'd
have to use an external search index like Lucene and perform my search
queries on that instead.

Does all this sound about right? Are there even simpler ways to go about
the by_user/global_tags features, like using only one view instead of
two separate ones (I've tried, but didn't succeed)?

Are there ways to use boolean queries without an external search index,
that I just can't find?

Thanks for your time!

CU
 Markus


Mime
View raw message