getting document which are referenced to in other document
Hi,
I'm used to SQL and I'm having trouble solving a problem. I'll to try to explain using the following example.
In the following "has many" construction, books are listed in a category:
Category document:
{
category: "Fantasy",
books: [12,231,563,312,23,5236]
}
Book document:
{
title: "Foo",
likes: 235
}
It would probably be better to use a "belongs to" model, but this is better to answer my question.
How would I get all books from the category "fantasy" ordered by likes descending? What would the view look like?
In addition to the nice answer from chrhlnd that gives you one approach, I am inviting you to read the "Modeling Documents" of the develop guide:
http://www.couchbase.com/docs/couchbase-devguide-2.0/modeling-documents....
Regards
Thanks! In your opinion would it matter if I stored the list "Fantasy_Books_Sorted_By_Author", In a separate document or just as a value of the category document? I'm guessing it shouldn't matter.
Also would only the bookID service? Or should the authors name also be included in the list? If only the bookID was listed how would this effect the performance, assuming it then should do multiple gets to book documents?
Heh its been bugging me till I could get back here. I forgot we're in the couchbase 2.0 forum. You should use a view for this. This is a major feature they added.
http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views.html
You could just have a category list inside your book object. Then make a view for every category only putting those items appropriate into each view. It also supports sorting the output. There is some documentation there that explains how order by maps to the view query.
Code would be something like
def mySuperListAppend( store, basekey, value ): useable_index = store.incr( basekey ) - 1 worked = store.add( basekey + str(useable_index), value ) if not worked: raise Exception("Why is there a key here") # possibly don't care if there is a key here use below instead # store.set( basekey + str(useable_index), value ) def mySuperListEnumerate( store, basekey, callmeFN ): max_index = store.get( basekey ) for i in range(max_index): data = store.get( basekey + str(i) )[0] # maybe error check data ? callmeFN( basekey + str(i), data ) -- somewhere else cb_bucket = <code that gets the cb bucket I care about> for book in BIGBOOKLIST_DATA_I_HAVE_FROM_EXTERNAL_SOURCE: mySuperListAppend(cb_bucket, 'Book', book) -- another place in the code def fillinIfFantasy( key, book ): if ISFANTASYBOOK(book): mySuperListAppend( cb_bucket, 'Fantasy_Book', key ) mySuperListEnumerate( cb_bucket, 'Book', fillinIfFantasy ) -- another place in the code def iterateFantasyBooks( store, processBookFN ): def lookupRealBook( key, value ): processBookFN( store.get( value ) ) mySuperListEnumerate( store, 'Fantasy_Book', lookupRealBook ) def printBook( book ): if book: print('fantasy book', book) iterateFantasyBooks( cb_bucket, printBook )Not sure if python is your thing should be straight forward though.
You could filter on insert as well.
Removing makes holes I recommend just ignoring null key. Or possibly keep another list of null indexes and fill them on insertion. As far as sorting them, you gotta pull them all into memory and do it yourself or possibly keep another list pointing at fantasy books, that is sorted by something, and binary insert into it.
Granted that could get a bit complicated. You'd use the list and run a binary search algorithm over it sorting items, then inserting the results of the sort as another list.. Fantasy_Books_Sorted_By_Author. Then you'd have to be careful to keep that list in sync with new items added to Fantasy_Books. Or just regenerate it at some point. Probably best to hide it all behind some library.
KV stores lack a lot of things from databases.
TL;DR; heh you do it yourself.