node.jscouchdbcouchdb-futon

Couchdb views return rows in rows


I am trying to create a view that returns the name with the price changes from the doc.

"name": "USD"
"price_changes": {
    "0min": 0,
    "15min": 0,
    "30min": 0,
    "60min": 0,
    "90min": 0,
    "120min": 0,
    "150min": 0,
    "180min": 0,
    "210min": 0,
    "240min": 0,
    "270min": 0,
    ...

What I want is a view that returns all the data in "price_changes".

{"id":"c95718ebd00b13bc9a8b03a0e5005d51",
"key": {"0min":0,"15min":0,"30min":0,"60min":0,"90min":0,"120min":0,"150min":0,...}
{"id":"c95718ebd00b13bc9a8b03a0e5006906",
"key": {"0min":0,"15min":0,"30min":0,"60min":0,"90min":0,"120min":0,"150min":0,...}
...

And views that return a set of the rows, like only "0mins", "15mins" and "30mins" for each name.

Like:

"id":"c95718ebd00b13bc9a8b03a0e5005d51",
"name": "USD", 
"key": {"0min":0,"15min":0,"30min":0}

Separately

"id":"c95718ebd00b13bc9a8b03a0e5006906",
"name": "GBP", 
"key": {"0min":0,"15min":0,"30min":0}

What I have so far is (but doesn't return what I want):

function (doc) {
var mins, value;
if (doc.price_changes) {
  for (mins in doc.price_changes) {
    value = doc.price_changes[mins];
    emit(doc.id, [value], mins);
    }
  }
}

Any idea guys? I can't really find anything on returning data like this.


Solution

  • Firstly, in your view map function, you're emitting three things:

    emit(doc.id, [value], mins);
    

    Which is not what it should be. As documented, you need to emit key/value pairs (well, of course, key or value can be an array of many things):

    Map functions accept a single document as the argument and (optionally) emit() key/value pairs that are stored in a view.


    According to what you say:

    What I want is a view that returns all the data in "price_changes".

    My understanding is that you need the following map function:

    function (doc) {
      var mins, value;
      if (doc.price_changes) {
        for (mins in doc.price_changes) {
          value = doc.price_changes[mins];
          emit(mins, [value, doc._id]);
        }
      }
    }
    

    And it returns:

    $ curl -k -X GET https://admin:****@192.168.1.106:6984/sample-repl/_design/price/_view/price
    {"total_rows":11,"offset":0,"rows":[
    {"id":"so_q","key":"0min","value":[0,"so_q"]},
    {"id":"so_q","key":"120min","value":[0,"so_q"]},
    {"id":"so_q","key":"150min","value":[0,"so_q"]},
    {"id":"so_q","key":"15min","value":[0,"so_q"]},
    {"id":"so_q","key":"180min","value":[0,"so_q"]},
    {"id":"so_q","key":"210min","value":[0,"so_q"]},
    {"id":"so_q","key":"240min","value":[0,"so_q"]},
    {"id":"so_q","key":"270min","value":[0,"so_q"]},
    {"id":"so_q","key":"30min","value":[0,"so_q"]},
    {"id":"so_q","key":"60min","value":[0,"so_q"]},
    {"id":"so_q","key":"90min","value":[0,"so_q"]}
    ]}
    

    I'm not sure if the above result is what you want, please let me know if I'm wrong.


    Thanks! Just wondering how would I return say the first 3 (like: 0min, 15min, 30min)

    To get the first 3, you can use limit query parameter like this, as you can see, it will return the first 3:

    $ curl -k -X GET https://admin:****@192.168.1.106:6984/sample-repl/_design/price/_view/price?limit=3
    {"total_rows":11,"offset":0,"rows":[
    {"id":"so_q","key":"0min","value":[0,"so_q"]},
    {"id":"so_q","key":"120min","value":[0,"so_q"]},
    {"id":"so_q","key":"150min","value":[0,"so_q"]}
    ]}
    

    In general, you can play around with query parameters to get what you want out of the view/index.