Unique values of a specific field in the collection

I’m looking for a way to get a list of the unique values of a specific field.

The scenarios below are completely imaginary.

Let’s say I have answeredBy field in collection ClientCalls. It contains the username of who answered the call. Teh first phase is to get a list of all the users who answered calls today, in a publication. The next phase is to include the counts in a similar publication.

Let’s say there were 5k answered client calls today. There is a page where the manager selects from the list of who answered calls today. Then s/he sees that person’s answers to client calls.

So I want to get a list of personnel who answered calls today. I need to return unique values of ClientCalls.answeredBy.

I can easily do

var Records = ClientCalls.find({answeredDate: Today}, {fields: {Personnel: 1}}).fetch()
return _.uniq(_.pluck(Records, 'Personnel')

and this gives me the list I need, but doing this in a publication causes Error: Publish function returned an array of non-Cursors.

I could easily return all the calls in a publication and do the uniq on the clientside, but it would mean a lot of unnecessary resource usage.

In the Meteor docs, it says to use .find() to create cursors.

So, how do I return a list of unique usernames as a cursor?

You can use the distinct method. However, this is not available in minimongo, so you will need to use Collection.rawCollection().distinct() on the server.

I got object if not a function for rawCollection()., so I used rawCollection..
Then I got Can only call rawCollection on server collections, so I moved the collection definition under the server/ folder.

Yet I still get the same error message. The collection is not defined anywhere else, but I still the get the same error message.

In lib/Demo.js

Demo = new Mongo.Collection('demo');

In server/demo.js

Meteor.startup(function() {
  if (Demo.find().count() === 0) {
    Demo.insert({name:'Bob',customer:'ACME',value:1234.56});
    Demo.insert({name:'Ted',customer:'ACME',value:5432.10});
    Demo.insert({name:'Ted',customer:'Oops',value:543.21});
    Demo.insert({name:'Bob',customer:'Spot',value:999.99});
  }
});

Demo.rawCollection().distinct('name', (err,res) => {
  console.log(res);
});

Outputs

I20160324-11:49:09.664(0)? [ 'Bob', 'Ted' ]

rawCollection() methods use standard node (error, result) callbacks, so you will need to use wrapAsync to use them productively in Meteor:

const distinct = Meteor.wrapAsync(Demo.rawCollection().distinct, Demo.rawCollection());
const result = distinct('name');
console.log(result);
1 Like