Johannes
Johannes

Reputation: 335

How to collect all tags and count these in Meteor

i need exactly this map/reduce function in meteor: http://cookbook.mongodb.org/patterns/count_tags/

Read all tags from all entries and give back a list of unique tags with the amount in the collection

How would I implement this. I'm using standalone Mongodb. Collection Layout:

[_id] => 1234
[headline] => My First Post
[body] => Alot of stuff
[isPrivat] => 
[tags] => Array (
    [0] => test
    [1] => php
    [2] => perl
)

I found this question/answer, but I can't get this to do what I wan't :
Does Meteor have a distinct query for collections?

What is the most elegant way to do this. Thank you for your time

Upvotes: 4

Views: 2561

Answers (3)

kynan
kynan

Reputation: 13643

You could try the meteor-mongo-extensions smart package, which implements some of MongoDB's aggregation framework functions for Meteor (disclaimer: I haven't tried it myself).

Another solution you might find helpful is sketched in pull request #644.

Upvotes: 2

Johannes
Johannes

Reputation: 335

I used the a.js lib to have the distinct code search suggested from here. Does Meteor have a distinct query for collections?

And this ugly one:

Template.Tag.taglist = function () {

    var taglist = Posts.find({}).distinct("tags");
    taglist = _.compact(_.flatten(_.pluck(taglist, 'tags')));
    // reformat, count and filter doublets 
    function counttags(arr) {
        var a = [], b = [], prev;
        arr.sort();
        for ( var i = 0; i < arr.length; i++ ) {
            if ( arr[i] !== prev ) {
                a.push(arr[i]);
                b.push(1);
            } else {
                b[b.length-1]++;
            }
            prev = arr[i];
        }
        result = _.zip(a,b);
        return result;
    }
    var taglist = counttags(taglist);

    //console.log(taglist);

    return taglist;
};

and the (simplified) template:

<template name="Tag">
    {{#each taglist}}
        {{this.[0]}}x {{this.[1]}}
    {{/each}}
 </template>

It's not very beautiful. once the aggregate or map/reduce methods are available I will swap the code. But for prototyping this works. Thanks everyone.

Upvotes: 1

Andrew Orsich
Andrew Orsich

Reputation: 53685

At the current moment, the most elegant solution would be aggregation framework:

db.items.aggregate(
    { $unwind : "$tags" },
    { $group : {
        _id : "$tags",
        count: { $sum : 1 }
    }}
);

It will output result like this one:

{ "result" : [ 
    { "_id" : "perl",
      "count" : 2 }, 
    { "_id" : "php",
      "count" : 1 }, 
    { "_id" : "test",
      "count" : 1 }],
  "ok" : 1 }

This is mongodb shell syntax. I not familiar with meteor, so I'll not try to write some code. Hope this helps!

Upvotes: 8

Related Questions