How could I get the reduced result and its value using Couchbase::View?


#1

Ruby SDK => v.1.3
Couchbase server => v.2.2

I have the following code…

models/my_view/map.js

function (doc, meta) { emit(meta.id, 1); }

models/my_view/reduce.js

function (key, values, rereduce) {
  // This is a built-in count reduce
  if (rereduce) {
        var result = 0;
        for (var i = 0; i < values.length; i++) {
            result += values[i];
        }
        return result;
    } else {
        return values.length;
    }
}

models/my_couchbase_model.rb

class MyCouchbaseModel.rb < Couchbase::Model
    view :my_view
end

controllers/my_controller.rb

def index
    count = MyCouchbaseModel.my_view
    puts count
    # #<Couchbase::View:0x007fa880b42c80>
    # => nil
end

It looks like count is nil.
How could I get the reduced result and its value?
Am I doing something wrong here?


#2

Why don’t you just use _count in the reduce.js function? Also, you don’t need to emit meta.id as the key, since it always gets sent over in non-reduced cases (and in reduced it doesn’t matter anyways here)


#3

when you say puts count it will print the object to STDOUT by calling to_s method on it. Here in Couchbase::View this method will output the object itself, just like you call puts count.inspect.

The nil in your example, probably the value returned by the puts which always returns nil: https://github.com/ruby/ruby/blob/c1397c573e0463dad6a395078b6aa267e85400ea/io.c#L7139

if you need to access actual results, the Couchbase::View returns, you need to enumerate them with each or converting to Array

http://www.rubydoc.info/gems/couchbase/Couchbase/View#each-instance_method


#4

In particular, from the beer sample mentioned above

Instantiating query in controller app/controllers/countries_controller.rb

def index
  @countries = Brewery.by_country
end

Fetching and rendering results in view app/views/countries/index.html.erb

<% @countries.each do |country| %>
  <tr>
    <td>
      <%= link_to country.key, country_path(country) %>
      <span class="badge pull-right"><%= country.value %></span>
    </td>
  </tr>
<% end %>

#5

@daschl
Actually, my code is much different and complicated. I just wrote a sample code since I could not access the actual results of reduced data.

@avsej
I already have tried the followings:

MyCouchbaseModel.my_view.count
MyCouchbaseModel.my_view.to_a

MyCouchbaseModel.my_view.each do |row|
    puts row.inspect
end

Everything gives me TypeError: no implicit conversion of nil into String
:frowning:

Plus,
Everything works fine on the couchbase web console.
If I do MyCouchbaseModel.my_view(:reduce => false).count, it gives me the count.


#6

I solved the problem~!!

MyCouchbaseModel.my_view(:include_docs => false)

If I did this, everything is working fine.
Now, my question is what does :include_docs actually do?

And it looks like the API states that :include_docs is false as default.
http://www.rubydoc.info/gems/couchbase/Couchbase/View
How come my application’s :include_docs is set as true? (weird…)


#7

Because in model context, it flips default, because it most cases you do need load document bodies


#8

@avsej
I see.
Then, do you know why I get TypeError: no implicit conversion of nil into String when :include_docs => true?


#9

I think that because when include_docs specified, it tries to fetch the document body using its ID, and obviously there no id attribute in the reduced results