title: MongoDB Aggregate lookup in Go (mgo.v2)
body: <p>I'm trying to implement <code>$lookup</code> functionality in one of my mongoDB queries in go (golang) using the <a href="https://godoc.org/gopkg.in/mgo.v2" rel="nofollow noreferrer">mgo</a> package.</p>
  
  <p>Below are my collections:</p>
  
  <p><strong>folders:</strong></p>
  
  <pre><code>"_id"    : ObjectId("22222222222222"),
  "name"   : "Media",
  "level"  : 1,
  "userIDs": [ObjectId("4444444444444")]
  </code></pre>
  
  <p><strong>documents:</strong></p>
  
  <pre><code>"_id"      : ObjectId("11111111111111"),
  "title"    : "Media Management",
  "body"     : BinData(0,"PvQ6z2NBm4265duo/e2XsYxA5bXKo="),
  "level"    : 1,
  "folderID" : ObjectId("22222222222222"), // Foreign Key/Field
  "userIDs"  : [ObjectId("44444444444444")]
  </code></pre>
  
  <p>Below is the query I've written that successfully runs on the shell:</p>
  
  <pre><code>var query = [
  { 
    "$lookup": {
      "from":         "documents",
      "localField":   "_id",
      "foreignField": "folderID",
      "as":           "documents",
    }
  }
   ,{
     "$match": {
        "userIDs": ObjectId("userIdHere"), // filder by a userID
        "level": {$gte: 0},                // filter by a folder level
      },
    }
  ];
  
  db.folders.aggregate(query).pretty().shellPrint();
  </code></pre>
  
  <p>If I run this script on the shell, I get the desired result. Basically, the <code>folder</code> collection is returned to me containing the full relevant <code>documents</code> that were linked through the <code>$lookup</code>. I'm not including it here because this question already seems too long.</p>
  
  <p>I've tried to translate this query into something that <em>mgo</em> would be able to parse and execute. Here it is below in go code:</p>
  
  <pre><code>query := bson.M{
    "$lookup": bson.M{ // lookup the documents table here
    "from":         "documents",
    "localField":   "_id",
    "foreignField": "folderID",
    "as":           "documents",
  },
    "$match": bson.M{
      "level":   bson.M{"$gte": user.Level}, // filter by level
      "userIDs": user.ID,                    // filter by user
    },
  }
  
  pipe := collection.Pipe(query) // querying the "folders" collection
  err := pipe.All(&amp;result)
  </code></pre>
  
  <p>I always get the same error: <strong>wrong type for field (pipeline) 3 != 4</strong></p>
  
  <p>If I understand correctly, it's because it can't properly parse the result back into the $result object. I've done everything I can to ensure the struct has the exact structure that is required. I've also tried to pass in a genereric <code>[]interface{}</code> and an empty <code>bson.M{}</code> objects. Still receive the same error.</p>
  
  <p>Below is my Folders struct:</p>
  
  <pre><code>type Folder struct {
    ID        bson.ObjectId   `json:"id" bson:"_id"`
    Name      string          `json:"name"`
    Level     int             `json:"level"`
    UserIDs   []bson.ObjectId `json:"userIDs" bson:"userIDs"`
    Users     []User          `json:"-" bson:"-"` // doesn't get stored in the database
    Documents []Document      `json:"-" bson:"-"` // doesn't get stored in the database
  }
  </code></pre>
  
  <p>I've also removed the <code>$match</code> clause to see if I could get anything at all back from that <code>$lookup</code> query. But I still get the same error.</p>
  
  <p>Perhaps the mgo package doesn't support <code>$lookup</code>? If so, would there be another way? <strong>Perhaps I could send the raw query text to mongo and receive the raw response and parse it myself?</strong></p>