Accept doc.key instead of doc.value for group-by/distinct mapreduce views
jasonm opened this issue · comments
A little context: I have an application with readers and scans, but the only documents I record into Couch are the scans, which contain a reader_description field.
I'd like to have a read-only collection of Readers, containing the distinct set of reader_description fields from the scans collection, so I have a map-reduce view function to emit distinct reader docs:
# to be used with group=true
distinctReadersFromScans:
map: (doc) ->
if doc.collection == 'scan'
readerDoc = { name: doc.reader_description }
emit(readerDoc, doc)
reduce: (keys, values) ->
null
I found this approach on http://stackoverflow.com/questions/2534376/how-do-i-do-the-sql-equivalent-of-distinct-in-couchdb
However, the HTTP response is formatted like this:
{"rows":[
{"key":{"name":"Fake Reader Foxtrot"},"value":null},
{"key":{"name":"Fake Reader Waltz"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Blueberry"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Foxtrot"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Waltz"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Waltz Pro"},"value":null}
]}
and when backbone-couchdb's con.read_connection
is called, only the value is pushed into the collection:
if doc.value then _temp.push doc.value else _temp.push doc.doc
(From backbone-couchdb.coffee#L94)
which means that my models are populated will null, instead of attr objects like { name: 'Fake Reader Foxtrot' }
.
So, I patched the function to handle a null value and emit the key instead:
# JPM: handle group-by mapreduces
if _.isEqual(['key', 'value'], _.keys(doc)) && doc.value == null
_temp.push doc.key
else
if doc.value then _temp.push doc.value else _temp.push doc.doc
I'm pretty new to CouchDB and its idioms. Am I doing this right? Is this patch something that others would find helpful? Does it conflict with some other convention in Couch?
Thanks!