Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregate pipeline throws the error "A pipeline stage specification object must contain exactly one field."

db.audiofiles.aggregate({
    $match: {
        privacy: { $ne: "same" },
        date: { "$eq": "2017/04/25" },
        deleted: 0
    },
    $group: { "_id": "$to_email" }
});

I have used $match but still it is showing pipeline error as below.

assert: command failed: {
    "ok" : 0,
    "errmsg" : "A pipeline stage specification object must contain exactly one field.",
    "code" : 16435
} : aggregate failed
like image 843
Jagadeesh Avatar asked Apr 24 '17 09:04

Jagadeesh


2 Answers

I was also facing same error. My code was :

 db.getCollection('users').aggregate([
      {
          "$lookup":
          {     
              from: 'songs',
              localField: '_id',
              foreignField: 'artistId',              
              as: 'abc'              
          },
          "$project":
          {
              "name":1,
              "status":1,
              "abc":{"artistId":1, "name":1}
          }
      }
])

I resolved by adding { }.

db.getCollection('users').aggregate([
      {
          "$lookup":
          {     
              from: 'songs',
              localField: '_id',
              foreignField: 'artistId',              
              as: 'abc'              
          }
      }, // added braces
      { 
          "$project":
          {
              "name":1,
              "status":1,
              "abc":{"artistId":1, "name":1}
          }
      } // added braces
])

NOTE:: Make sure $lookup and $project should be in different {} braces like :

db.getCollection('users').aggregate([ { $lookup:{} }, { $project: {} } ])

My code was :

 db.getCollection('users').aggregate([ { $lookup:{},  $project: {} } ])
like image 134
HSP Avatar answered Sep 23 '22 18:09

HSP


You need to place your pipeline stages in an array, i.e. documents pass through the stages in sequence.

db.collection.aggregate( [ { <stage> }, ... ] )

The $group pipeline step operators should be in their own object/document, not as part of the $match pipeline step. You aggregate pipeline should be

db.audiofiles.aggregate([
    /* match pipeline */
    {
        "$match": {
            "privacy": { "$ne": "same" },
            "date": { "$eq": "2017/04/25" },
            "deleted": 0
        }
    },
    /* group pipeline */
    {
        "$group": { 
            "_id": "$to_email", 
            "count": { "$sum": 1 }
        }
    }
]);

Or create the pipeline steps as object variables that you can push to an array and that array becomes the pipeline to use as the aggregate() method argument:

/* match pipeline */
var match = {
    $match: {
        privacy: { $ne: "same" },
        date: { "$eq": "2017/04/25" },
        deleted: 0
    }
},
/* group pipeline */
group = {
    $group: { 
        "_id": "$to_email", 
        "count": { "$sum": 1 }
    }
};

db.audiofiles.aggregate([match, group]);

If you don't get any response from the above then try to run the aggregate pipeline with just one step:

db.audiofiles.aggregate([match]);

The results from the match step will be piped to the next stage so if you aren't getting any results that means the $match pipeline step hasn't found any matching documents. Change some of the parameters to see if there are any results.

like image 27
chridam Avatar answered Sep 21 '22 18:09

chridam