Return result as an Array of Values Only

2019-03-06 01:37发布

问题:

I have following collection

[ { _id: 5b12a7977990062f097d03ce,
    name: 'Breakfast',
    category: 'dining' },
  { _id: 5b12a7977990062f097d03d0,
    name: 'Brunch',
    category: 'dining' },
  { _id: 5b12a7977990062f097d03d2,
    name: 'Lunch',
    category: 'dining' } ]

I have to collect all the name having category dining in a main array

I have tried this

       const subCategory = await SubCategory.aggregate([
          { '$match': { category: "dining" }},
          { '$group': {
            '_id': null,
            'category': { '$push': '$name' }
          }}
        ])

But it gives me output like this

[ { _id: null,
    category: 
     [ 'Breakfast',
       'Brunch',
       'Lunch' ] } ]

And I want output like this

     [ 'Breakfast',
       'Brunch',
       'Lunch' ]

回答1:

You can map(). Use Array.map() with mongoose as it returns an array, and you are better off simply using the $group _id than using $push

const subCategory = (await SubCategory.aggregate([
  { '$match': { category: "dining" } },
  { '$group': { '_id': "$name" } }
])).map(({ _id }) => _id);

Or with Cursor.map() if using the underlying Collection from the core driver:

const subCategory = await SubCategory.collection.aggregate([
  { '$match': { category: "dining" } },
  { '$group': { '_id': "$name"  } }
]).map(({ _id }) => _id).toArray();

Much the same with find() if you don't want the "distinct" results:

const subCategory = (await Subcategory.find({ category: "dining" }))
  .map(({ name }) => name);

Or with the Cursor.map()

const subCategory = await Subcategory.collection.find({ category: "dining" })
  .map(({ name }) => name).toArray();

You can also use distinct(), which basically does a variation of the aggregation process and the map() "under the hood" ( the "return just the field part" and not the distinct aggregation method ):

const subCategory = await SubCategory.distinct("name",{ category: "dining" });

MongoDB itself won't return anything other than a BSON Document, and a simple string is NOT a BSON Document.



回答2:

db.mycoll.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $match: {
                category: 'dining'
            }
        },

        // Stage 2
        {
            $group: {
                _id: null,
                category: {
                    $addToSet: '$name'
                }
            }
        },

        // Stage 3
        {
            $out: "temp"
        }

    ]

The resultset obtained upon execution of above aggregate query will be stored into a temporary collection temp

Into next stage we can execute following operation to obtain result as an array.

db.temp.distinct('name')