0
votes

Good morning, I'm currently working with Couchdb and Pouchdb and I'm having a problem with one query on Pouchdb side.

I have a database with different documents setup like this:

{
  "_id": "fd87b66087503d760fa501fa49029f94",
  "_rev": "1-e2be19d447c98d624c2c8492eaf0a3f4",
  "type": "product",
  "name": "Blanc de Morgex et de la Salle Brut Extreme 2014",
  "category": "Wine",
  "subcategory": null,
  "zone": "Italy",
  "nation": "Valle d'Aosta",
  "province": "Morgex, AO",
  "cellar": "Cave Mont Blanc",
  "price": 30,
  "structure": null,
  "year": 2014,
  "mescita": null,
  "tag": null
}

The query I wrote should return the available years of products that match some filters. This is the query, with reduce : _count:

function (doc) {
    if(doc.category && doc.type == 'product' && doc.year != null) {
        emit(doc.year , 1);
    }
}

If I try it with Postman adding the group = true parameter everything works and the result is something like:

{
    "rows": [
        {
            "key": 2004,
            "value": 2
        },
        {
            "key": 2006,
            "value": 2
        },
        {
            "key": 2008,
            "value": 2
        }
    ]
}

The problem is when i run this view with Pouchdb with the following code which return a JSON with an empty array:

wine_db.query('wine_list/years', {reduce: '_count', key : "Bollicine", group : true, group_level: 2}).then(function(doc) {
    years_list = doc;
    console.log('getting year list');
    console.log(doc);
}).catch(function(err){
    console.log(err);
});

I've tried to play a little with the parameters of the function and even changing the function to return just a list of all the years, but nope. I can't find the problem neither a different solution so I'm open to every suggestion you can have.


Another solution (group result)

Working on the indications and on the solution suggested by @user3405291 I finally found a way to group the results by year. Since the emit function return a complex key ['CATEGORY', YEAR] I can use the startkey and endkey parameters to query the result just for a section of the index returned keeping this way the reduce function enable to group the result.

In the end the view function is:

function (doc) {
    if(doc.category && doc.type == 'product' && doc.year) {
        emit([doc.category, doc.year], doc.year );
    }
}

And the Pouchdb query:

wine_db.query('wine_list/years', 
    {
        startkey : ['CATEGORY'],
        endkey : ['CATEGORY', {}],
        group: true
    }
).then(function (doc) {
    years_list = doc;
    console.log(years_list);
}).catch(function (err) {
    console.log(err);
}); 

The result, where value is the total number of elements with that index:

{
    "rows": [
        {
            "key": [
                "Bollicine",
                2004
            ],
            "value": 2
        },
        {
            "key": [
                "Bollicine",
                2006
            ],
            "value": 2
        },
        {
            "key": [
                "Bollicine",
                2008
            ],
            "value": 2
        }
    ]
}
1

1 Answers

0
votes

In your view map function you emit the year as the key/index:

emit(doc.year , 1);

Now, I'm not sure why your are doing your query with a key like {key : "Bollicine"}:

wine_db.query('wine_list/years', {key : "Bollicine"})
.then(res=>{console.log(res)})

Of course you would get an empty response, because your view is actually indexing your docs according to year. I think you might want to do a query with a key like: {key : "2014"}


UPDATE

Based on your comments, I feel like you need to find docs based on both year and category. I'm not sure if I understand what you want, but this may help you: change your view map function like this:

function (doc) {
    if(doc.category && doc.type == 'product' && doc.year) {
        emit([doc.year, doc.category] , 1);
    }
}

The above view will index your docs according to both year and category. You then query your view like this:

wine_db.query('wine_list/years', {key : ['2014', 'Bollicine']})
.then(res=>{console.log(res)})

The above query will give you all the docs with year field equal to 2014 and category field equal to Bollicine.


Second Update

your code works, but I just get the result for the year 2014. What I'm trying to accomplish is to get all the available years given a specific category

One solution is this:

function (doc) {
    if(doc.category && doc.type == 'product' && doc.year) {
        emit(doc.category, doc.year);
    }
}

The above view will index your docs according to category as key and will return the year as value. Therefore you can query like this:

wine_db.query('wine_list/years', {key : 'Bollicine'})
.then(res=>{console.log(res)})

You should get a response like this, by which you have all the available years for Bollicine category:

{
    "total_rows": 400,
    "offset": 0,
    "rows": [
        {
            "key": "Bollicine",
            "value": "2014"
        },

        {
            "key": "Bollicine",
            "value": "2015"
        },

        {
            "key": "Bollicine",
            "value": "2018"
        }

    ]
}