Startec
Startec

Reputation: 13206

Mongoose, concise way to get one item with each unique property into an array?

I have a collection of documents with many different characteristics. I want to get from Mongoose an array where each item in the array is a unique value for an attribute, in this case color. In other words, I do not want an array of each item, just of the color values. So in this case, if I have 100 different products, but only 8 colors between all 100, then I would like the to have an array of the 8 colors. Here is the way I have been using but I am wondering if there is a more concise way of doing it?

  var allproducts = Products.find(function (err, products) {
    // Get all products
    var collection = [];
    // Make an array to contain a product with each of the 8 colors
    var uniqueArray = [];
    // Make an array to check the current color against (if already used)
    for (var i = products.length - 1; i >= 0; i--) {
      if (uniqueArray.indexOf(products[i].color) === -1) {
        // Check to see if the color is in the unique color array
        uniqueArray.push(products[i].color);
        // Add it if not
        collection.push(products[i]);
        // Add the product to the collection array if its color is not in the unique array
      }
    }
  });

Attempting to use the Mongoose aggregate method:

router.get('/', function (req, res) {
  Products.aggregate([{
    $group: {
      _id: '$color'
    }
  }], {}, function (err, collection) {
    console.log(err, collection);
    if (err) {
      throw err
    }
    res.end();
    // res.json(collection);
  });
});

Upvotes: 0

Views: 672

Answers (2)

Maçois
Maçois

Reputation: 9

I. Directly in mongodb, you have to this request :

 db.colors.aggregate( { $group: {_id:"$color"} } )

Result :

{ "_id" : "yellow" }
{ "_id" : "blue" }
{ "_id" : "red" }

MongoDB Tutorial for aggregation

II. In mongoose you can do :

Products.aggregate(
     {$group: {
            _id: '$color' // grouping key - group by field district
     }
 }).exec( function( err, products ) {
    if ( err ) {
      return res.status( 400 ).send({
        message: errorHandler.getErrorMessage( err )
      });
    } else {
      res.json( products );
    }
 });

Mongoose : Model aggregate

Upvotes: 1

Ben Diamant
Ben Diamant

Reputation: 6206

This can be easily solved using lodash

npm install lodash --save

var _ = require('lodash');

var allproducts = Products.find(function (err, products) {
    ...
    var uniqueArray = _.pluck(products, 'color');
    uniqueArray = _.uniq(uniqueArray);
    ....  
});

Upvotes: 1

Related Questions