text: /*
    Run all the aggregation tests
  */
  
  /* load the test documents */
  load('jstests/aggregation/data/articles.js');
  
  // make sure we're using the right db; this is the same as "use mydb;" in shell
  db = db.getSiblingDB("aggdb");
  
  // just passing through fields
  var p1 = db.runCommand({aggregate: "article", pipeline: [{$project: {tags: 1, pageViews: 1}}]});
  
  var p1result = [
      {"_id": 1, "pageViews": 5, "tags": ["fun", "good", "fun"]},
      {"_id": 2, "pageViews": 7, "tags": ["fun", "nasty"]},
      {"_id": 3, "pageViews": 6, "tags": ["nasty", "filthy"]}
  ];
  
  assert.docEq(p1.result, p1result, 'p1 failed');
  
  // a simple array unwinding
  var u1 = db.runCommand({aggregate: "article", pipeline: [{$unwind: "$tags"}]});
  
  var u1result = [
      {
        "_id": 1,
        "title": "this is my title",
        "author": "bob",
        "posted": ISODate("2004-03-21T18:59:54Z"),
        "pageViews": 5,
        "tags": "fun",
        "comments":
            [{"author": "joe", "text": "this is cool"}, {"author": "sam", "text": "this is bad"}],
        "other": {"foo": 5}
      },
      {
        "_id": 1,
        "title": "this is my title",
        "author": "bob",
        "posted": ISODate("2004-03-21T18:59:54Z"),
        "pageViews": 5,
        "tags": "good",
        "comments":
            [{"author": "joe", "text": "this is cool"}, {"author": "sam", "text": "this is bad"}],
        "other": {"foo": 5}
      },
      {
        "_id": 1,
        "title": "this is my title",
        "author": "bob",
        "posted": ISODate("2004-03-21T18:59:54Z"),
        "pageViews": 5,
        "tags": "fun",
        "comments":
            [{"author": "joe", "text": "this is cool"}, {"author": "sam", "text": "this is bad"}],
        "other": {"foo": 5}
      },
      {
        "_id": 2,
        "title": "this is your title",
        "author": "dave",
        "posted": ISODate("2030-08-08T04:11:10Z"),
        "pageViews": 7,
        "tags": "fun",
        "comments": [
            {"author": "barbara", "text": "this is interesting"},
            {"author": "jenny", "text": "i like to play pinball", "votes": 10}
        ],
        "other": {"bar": 14}
      },
      {
        "_id": 2,
        "title": "this is your title",
        "author": "dave",
        "posted": ISODate("2030-08-08T04:11:10Z"),
        "pageViews": 7,
        "tags": "nasty",
        "comments": [
            {"author": "barbara", "text": "this is interesting"},
            {"author": "jenny", "text": "i like to play pinball", "votes": 10}
        ],
        "other": {"bar": 14}
      },
      {
        "_id": 3,
        "title": "this is some other title",
        "author": "jane",
        "posted": ISODate("2000-12-31T05:17:14Z"),
        "pageViews": 6,
        "tags": "nasty",
        "comments": [
            {"author": "will", "text": "i don't like the color"},
            {"author": "jenny", "text": "can i get that in green?"}
        ],
        "other": {"bar": 14}
      },
      {
        "_id": 3,
        "title": "this is some other title",
        "author": "jane",
        "posted": ISODate("2000-12-31T05:17:14Z"),
        "pageViews": 6,
        "tags": "filthy",
        "comments": [
            {"author": "will", "text": "i don't like the color"},
            {"author": "jenny", "text": "can i get that in green?"}
        ],
        "other": {"bar": 14}
      }
  ];
  
  assert.docEq(u1.result, u1result, 'u1 failed');
  
  // unwind an array at the end of a dotted path
  db.ut.drop();
  db.ut.save({_id: 4, a: 1, b: {e: 7, f: [4, 3, 2, 1]}, c: 12, d: 17});
  var u2 = db.runCommand({aggregate: "ut", pipeline: [{$unwind: "$b.f"}]});
  
  var u2result = [
      {"_id": 4, "a": 1, "b": {"e": 7, "f": 4}, "c": 12, "d": 17},
      {"_id": 4, "a": 1, "b": {"e": 7, "f": 3}, "c": 12, "d": 17},
      {"_id": 4, "a": 1, "b": {"e": 7, "f": 2}, "c": 12, "d": 17},
      {"_id": 4, "a": 1, "b": {"e": 7, "f": 1}, "c": 12, "d": 17}
  ];
  
  assert.docEq(u2.result, u2result, 'u2 failed');
  
  // combining a projection with unwinding an array
  var p2 = db.runCommand({
      aggregate: "article",
      pipeline: [{$project: {author: 1, tags: 1, pageViews: 1}}, {$unwind: "$tags"}]
  });
  
  var p2result = [
      {"_id": 1, "author": "bob", "pageViews": 5, "tags": "fun"},
      {"_id": 1, "author": "bob", "pageViews": 5, "tags": "good"},
      {"_id": 1, "author": "bob", "pageViews": 5, "tags": "fun"},
      {"_id": 2, "author": "dave", "pageViews": 7, "tags": "fun"},
      {"_id": 2, "author": "dave", "pageViews": 7, "tags": "nasty"},
      {"_id": 3, "author": "jane", "pageViews": 6, "tags": "nasty"},
      {"_id": 3, "author": "jane", "pageViews": 6, "tags": "filthy"}
  ];
  
  assert.docEq(p2.result, p2result, 'p2 failed');
  
  // pulling values out of subdocuments
  var p3 = db.runCommand({
      aggregate: "article",
      pipeline: [{$project: {otherfoo: "$other.foo", otherbar: "$other.bar"}}]
  });
  
  var p3result = [{"_id": 1, "otherfoo": 5}, {"_id": 2, "otherbar": 14}, {"_id": 3, "otherbar": 14}];
  
  assert.docEq(p3.result, p3result, 'p3 failed');
  
  // projection includes a computed value
  var p4 = db.runCommand({
      aggregate: "article",
      pipeline: [{$project: {author: 1, daveWroteIt: {$eq: ["$author", "dave"]}}}]
  });
  
  var p4result = [
      {"_id": 1, "author": "bob", "daveWroteIt": false},
      {"_id": 2, "author": "dave", "daveWroteIt": true},
      {"_id": 3, "author": "jane", "daveWroteIt": false}
  ];
  
  assert.docEq(p4.result, p4result, 'p4 failed');
  
  // projection includes a virtual (fabricated) document
  var p5 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: 1, pageViews: 1, tags: 1}},
          {$unwind: "$tags"},
          {$project: {author: 1, subDocument: {foo: "$pageViews", bar: "$tags"}}}
      ]
  });
  
  var p5result = [
      {"_id": 1, "author": "bob", "subDocument": {"foo": 5, "bar": "fun"}},
      {"_id": 1, "author": "bob", "subDocument": {"foo": 5, "bar": "good"}},
      {"_id": 1, "author": "bob", "subDocument": {"foo": 5, "bar": "fun"}},
      {"_id": 2, "author": "dave", "subDocument": {"foo": 7, "bar": "fun"}},
      {"_id": 2, "author": "dave", "subDocument": {"foo": 7, "bar": "nasty"}},
      {"_id": 3, "author": "jane", "subDocument": {"foo": 6, "bar": "nasty"}},
      {"_id": 3, "author": "jane", "subDocument": {"foo": 6, "bar": "filthy"}}
  ];
  
  assert.docEq(p5.result, p5result, 'p5 failed');
  
  // multi-step aggregate
  // nested expressions in computed fields
  var p6 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: 1, tags: 1, pageViews: 1}},
          {$unwind: "$tags"},
          {
            $project: {
                author: 1,
                tag: "$tags",
                pageViews: 1,
                daveWroteIt: {$eq: ["$author", "dave"]},
                weLikeIt: {$or: [{$eq: ["$author", "dave"]}, {$eq: ["$tags", "good"]}]}
            }
          }
      ]
  });
  
  var p6result = [
      {
        "_id": 1,
        "author": "bob",
        "pageViews": 5,
        "tag": "fun",
        "daveWroteIt": false,
        "weLikeIt": false
      },
      {
        "_id": 1,
        "author": "bob",
        "pageViews": 5,
        "tag": "good",
        "daveWroteIt": false,
        "weLikeIt": true
      },
      {
        "_id": 1,
        "author": "bob",
        "pageViews": 5,
        "tag": "fun",
        "daveWroteIt": false,
        "weLikeIt": false
      },
      {
        "_id": 2,
        "author": "dave",
        "pageViews": 7,
        "tag": "fun",
        "daveWroteIt": true,
        "weLikeIt": true
      },
      {
        "_id": 2,
        "author": "dave",
        "pageViews": 7,
        "tag": "nasty",
        "daveWroteIt": true,
        "weLikeIt": true
      },
      {
        "_id": 3,
        "author": "jane",
        "pageViews": 6,
        "tag": "nasty",
        "daveWroteIt": false,
        "weLikeIt": false
      },
      {
        "_id": 3,
        "author": "jane",
        "pageViews": 6,
        "tag": "filthy",
        "daveWroteIt": false,
        "weLikeIt": false
      }
  ];
  
  assert.docEq(p6.result, p6result, 'p6 failed');
  
  // slightly more complex computed expression; $ifNull
  var p7 = db.runCommand({
      aggregate: "article",
      pipeline:
          [{$project: {theSum: {$add: ["$pageViews", {$ifNull: ["$other.foo", "$other.bar"]}]}}}]
  });
  
  var p7result = [{"_id": 1, "theSum": 10}, {"_id": 2, "theSum": 21}, {"_id": 3, "theSum": 20}];
  
  assert.docEq(p7.result, p7result, 'p7 failed');
  
  // dotted path inclusion; _id exclusion
  var p8 = db.runCommand({
      aggregate: "article",
      pipeline:
          [{$project: {_id: 0, author: 1, tags: 1, "comments.author": 1}}, {$unwind: "$tags"}]
  });
  
  var p8result = [
      {"author": "bob", "tags": "fun", "comments": [{"author": "joe"}, {"author": "sam"}]},
      {"author": "bob", "tags": "good", "comments": [{"author": "joe"}, {"author": "sam"}]},
      {"author": "bob", "tags": "fun", "comments": [{"author": "joe"}, {"author": "sam"}]},
      {"author": "dave", "tags": "fun", "comments": [{"author": "barbara"}, {"author": "jenny"}]},
      {"author": "dave", "tags": "nasty", "comments": [{"author": "barbara"}, {"author": "jenny"}]},
      {"author": "jane", "tags": "nasty", "comments": [{"author": "will"}, {"author": "jenny"}]},
      {"author": "jane", "tags": "filthy", "comments": [{"author": "will"}, {"author": "jenny"}]}
  ];
  
  assert.docEq(p8.result, p8result, 'p8 failed');
  
  // collapse a dotted path with an intervening array
  var p9 = db.runCommand({
      aggregate: "article",
      pipeline: [{$project: {_id: 0, author: 1, commentsAuthor: "$comments.author"}}]
  });
  
  var p9result = [
      {"author": "bob", "commentsAuthor": ["joe", "sam"]},
      {"author": "dave", "commentsAuthor": ["barbara", "jenny"]},
      {"author": "jane", "commentsAuthor": ["will", "jenny"]}
  ];
  
  assert.docEq(p9.result, p9result, 'p9 failed');
  
  // simple sort
  var p10 = db.runCommand({aggregate: "article", pipeline: [{$sort: {title: 1}}]});
  
  var p10result = [
      {
        "_id": 1,
        "title": "this is my title",
        "author": "bob",
        "posted": ISODate("2004-03-21T18:59:54Z"),
        "pageViews": 5,
        "tags": ["fun", "good", "fun"],
        "comments":
            [{"author": "joe", "text": "this is cool"}, {"author": "sam", "text": "this is bad"}],
        "other": {"foo": 5}
      },
      {
        "_id": 3,
        "title": "this is some other title",
        "author": "jane",
        "posted": ISODate("2000-12-31T05:17:14Z"),
        "pageViews": 6,
        "tags": ["nasty", "filthy"],
        "comments": [
            {"author": "will", "text": "i don't like the color"},
            {"author": "jenny", "text": "can i get that in green?"}
        ],
        "other": {"bar": 14}
      },
      {
        "_id": 2,
        "title": "this is your title",
        "author": "dave",
        "posted": ISODate("2030-08-08T04:11:10Z"),
        "pageViews": 7,
        "tags": ["fun", "nasty"],
        "comments": [
            {"author": "barbara", "text": "this is interesting"},
            {"author": "jenny", "text": "i like to play pinball", "votes": 10}
        ],
        "other": {"bar": 14}
      }
  ];
  
  assert.docEq(p10.result, p10result, 'p10 failed');
  
  // unwind on nested array
  db.p11.drop();
  db.p11.save({
      _id: 5,
      name: 'MongoDB',
      items: {authors: ['jay', 'vivek', 'bjornar'], dbg: [17, 42]},
      favorites: ['pickles', 'ice cream', 'kettle chips']
  });
  
  var p11 = db.runCommand({
      aggregate: "p11",
      pipeline: [{$unwind: "$items.authors"}, {$project: {name: 1, author: "$items.authors"}}, ]
  });
  
  p11result = [
      {"_id": 5, "name": "MongoDB", "author": "jay"},
      {"_id": 5, "name": "MongoDB", "author": "vivek"},
      {"_id": 5, "name": "MongoDB", "author": "bjornar"}
  ];
  
  assert.docEq(p11.result, p11result, 'p11 failed');
  
  // multiply test
  var p12 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project:
              {theProduct: {$multiply: ["$pageViews", {$ifNull: ["$other.foo", "$other.bar"]}]}}
      }]
  });
  
  var p12result =
      [{"_id": 1, "theProduct": 25}, {"_id": 2, "theProduct": 98}, {"_id": 3, "theProduct": 84}];
  
  assert.docEq(p12.result, p12result, 'p12 failed');
  
  // subtraction test
  var p13 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project: {
              theDifference:
                  {$subtract: ["$pageViews", {$ifNull: ["$other.foo", "$other.bar"]}]}
          }
      }]
  });
  
  var p13result = [
      {"_id": 1, "theDifference": 0},
      {"_id": 2, "theDifference": -7},
      {"_id": 3, "theDifference": -8}
  ];
  
  assert.docEq(p13.result, p13result, 'p13 failed');
  
  // mod test
  var p14 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project:
              {theRemainder: {$mod: [{$ifNull: ["$other.foo", "$other.bar"]}, "$pageViews", ]}}
      }]
  });
  
  var p14result =
      [{"_id": 1, "theRemainder": 0}, {"_id": 2, "theRemainder": 0}, {"_id": 3, "theRemainder": 2}];
  
  assert.docEq(p14.result, p14result, 'p14 failed');
  
  // toUpper test
  var p15 = db.runCommand(
      {aggregate: "article", pipeline: [{$project: {author: {$toUpper: "$author"}, pageViews: 1}}]});
  
  var p15result = [
      {"_id": 1, "author": "BOB", "pageViews": 5},
      {"_id": 2, "author": "DAVE", "pageViews": 7},
      {"_id": 3, "author": "JANE", "pageViews": 6}
  ];
  
  assert.docEq(p15.result, p15result, 'p15 failed');
  
  // toLower test
  var p16 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: {$toUpper: "$author"}, pageViews: 1}},
          {$project: {author: {$toLower: "$author"}, pageViews: 1}}
      ]
  });
  
  var p16result = [
      {
        "_id": 1,
        "author": "bob",
        "pageViews": 5,
      },
      {
        "_id": 2,
        "author": "dave",
        "pageViews": 7,
      },
      {
        "_id": 3,
        "author": "jane",
        "pageViews": 6,
      }
  ];
  
  assert.docEq(p16.result, p16result, 'p16 failed');
  
  // substr test
  var p17 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project: {
              author: {$substr: ["$author", 1, 2]},
          }
      }]
  });
  
  var p17result =
      [{"_id": 1, "author": "ob"}, {"_id": 2, "author": "av"}, {"_id": 3, "author": "an"}];
  
  assert.docEq(p17.result, p17result, 'p17 failed');
  
  // strcasecmp test
  var p18 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project: {
              tags: 1,
              thisisalametest: {$strcasecmp: ["foo", "bar"]},
              thisisalamepass: {$strcasecmp: ["foo", "foo"]}
          }
      }]
  });
  
  var p18result = [
      {"_id": 1, "tags": ["fun", "good", "fun"], "thisisalametest": 1, "thisisalamepass": 0},
      {"_id": 2, "tags": ["fun", "nasty"], "thisisalametest": 1, "thisisalamepass": 0},
      {"_id": 3, "tags": ["nasty", "filthy"], "thisisalametest": 1, "thisisalamepass": 0}
  ];
  
  assert.docEq(p18.result, p18result, 'p18 failed');
  
  // date tests
  var p19 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project: {
              authors: 1,
              posted: 1,
              seconds: {$second: "$posted"},
              minutes: {$minute: "$posted"},
              hour: {$hour: "$posted"},
              dayOfYear: {$dayOfYear: "$posted"},
              dayOfMonth: {$dayOfMonth: "$posted"},
              dayOfWeek: {$dayOfWeek: "$posted"},
              month: {$month: "$posted"},
              week: {$week: "$posted"},
              year: {$year: "$posted"}
          }
      }]
  });
  
  var p19result = [
      {
        "_id": 1,
        "posted": ISODate("2004-03-21T18:59:54Z"),
        "seconds": 54,
        "minutes": 59,
        "hour": 18,
        "dayOfYear": 81,
        "dayOfMonth": 21,
        "dayOfWeek": 1,
        "month": 3,
        "week": 12,
        "year": 2004,
      },
      {
        "_id": 2,
        "posted": ISODate("2030-08-08T04:11:10Z"),
        "seconds": 10,
        "minutes": 11,
        "hour": 4,
        "dayOfYear": 220,
        "dayOfMonth": 8,
        "dayOfWeek": 5,
        "month": 8,
        "week": 31,
        "year": 2030,
      },
      {
        "_id": 3,
        "posted": ISODate("2000-12-31T05:17:14Z"),
        "seconds": 14,
        "minutes": 17,
        "hour": 5,
        "dayOfYear": 366,
        "dayOfMonth": 31,
        "dayOfWeek": 1,
        "month": 12,
        "week": 53,
        "year": 2000,
      }
  ];
  
  assert.docEq(p19.result, p19result, 'p19 failed');
  
  db.vartype.drop();
  db.vartype.save({x: 17, y: "foo"});
  
  // ternary conditional operator
  var p21 = db.runCommand({
      aggregate: "article",
      pipeline: [{
          $project: {
              _id: 0,
              author: 1,
              pageViews: {
                  $cond:
                      [{$eq: ["$author", "dave"]}, {$add: ["$pageViews", 1000]}, "$pageViews"]
              }
          }
      }]
  });
  
  var p21result = [
      {"author": "bob", "pageViews": 5},
      {"author": "dave", "pageViews": 1007},
      {"author": "jane", "pageViews": 6}
  ];
  
  assert.docEq(p21.result, p21result, 'p21 failed');
  
  // simple matching
  var m1 = db.runCommand({aggregate: "article", pipeline: [{$match: {author: "dave"}}]});
  
  var m1result = [{
      "_id": 2,
      "title": "this is your title",
      "author": "dave",
      "posted": ISODate("2030-08-08T04:11:10Z"),
      "pageViews": 7,
      "tags": ["fun", "nasty"],
      "comments": [
          {"author": "barbara", "text": "this is interesting"},
          {"author": "jenny", "text": "i like to play pinball", "votes": 10}
      ],
      "other": {"bar": 14}
  }];
  
  assert.docEq(m1.result, m1result, 'm1 failed');
  
  // combining matching with a projection
  var m2 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {title: 1, author: 1, pageViews: 1, tags: 1, comments: 1}},
          {$unwind: "$tags"},
          {$match: {tags: "nasty"}}
      ]
  });
  
  var m2result = [
      {
        "_id": 2,
        "title": "this is your title",
        "author": "dave",
        "pageViews": 7,
        "tags": "nasty",
        "comments": [
            {"author": "barbara", "text": "this is interesting"},
            {"author": "jenny", "text": "i like to play pinball", "votes": 10}
        ]
      },
      {
        "_id": 3,
        "title": "this is some other title",
        "author": "jane",
        "pageViews": 6,
        "tags": "nasty",
        "comments": [
            {"author": "will", "text": "i don't like the color"},
            {"author": "jenny", "text": "can i get that in green?"}
        ]
      }
  ];
  
  assert.docEq(m2.result, m2result, 'm2 failed');
  
  // group by tag, _id is a field reference
  var g1 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: 1, tags: 1, pageViews: 1}},
          {$unwind: "$tags"},
          {$group: {_id: "$tags", docsByTag: {$sum: 1}, viewsByTag: {$sum: "$pageViews"}}},
          {$sort: {'_id': 1}}
      ]
  });
  
  var g1result = [
      {"_id": "filthy", "docsByTag": 1, "viewsByTag": 6},
      {"_id": "fun", "docsByTag": 3, "viewsByTag": 17},
      {"_id": "good", "docsByTag": 1, "viewsByTag": 5},
      {"_id": "nasty", "docsByTag": 2, "viewsByTag": 13},
  ];
  
  assert.docEq(g1.result, g1result, 'g1 failed');
  
  // $max, and averaging in a final projection; _id is structured
  var g2 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: 1, tags: 1, pageViews: 1}},
          {$unwind: "$tags"},
          {
            $group: {
                _id: {tags: "$tags"},
                docsByTag: {$sum: 1},
                viewsByTag: {$sum: "$pageViews"},
                mostViewsByTag: {$max: "$pageViews"},
            }
          },
          {
            $project: {
                _id: false,
                tag: "$_id.tags",
                mostViewsByTag: 1,
                docsByTag: 1,
                viewsByTag: 1,
                avgByTag: {$divide: ["$viewsByTag", "$docsByTag"]}
            }
          },
          {$sort: {'docsByTag': 1, 'viewsByTag': 1}}
      ]
  });
  
  var g2result = [
      {"docsByTag": 1, "viewsByTag": 5, "mostViewsByTag": 5, "tag": "good", "avgByTag": 5},
      {"docsByTag": 1, "viewsByTag": 6, "mostViewsByTag": 6, "tag": "filthy", "avgByTag": 6},
      {"docsByTag": 2, "viewsByTag": 13, "mostViewsByTag": 7, "tag": "nasty", "avgByTag": 6.5},
      {
        "docsByTag": 3,
        "viewsByTag": 17,
        "mostViewsByTag": 7,
        "tag": "fun",
        "avgByTag": 5.666666666666667
      }
  ];
  
  assert.docEq(g2.result, g2result, 'g2 failed');
  
  // $push as an accumulator; can pivot data
  var g3 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {
            $project: {
                author: 1,
                tags: 1,
            }
          },
          {$unwind: "$tags"},
          {$group: {_id: {tags: "$tags"}, authors: {$push: "$author"}}},
          {$sort: {'_id': 1}}
      ]
  });
  
  var g3result = [
      {"_id": {"tags": "filthy"}, "authors": ["jane"]},
      {"_id": {"tags": "fun"}, "authors": ["bob", "bob", "dave"]},
      {"_id": {"tags": "good"}, "authors": ["bob"]},
      {"_id": {"tags": "nasty"}, "authors": ["dave", "jane"]}
  ];
  
  assert.docEq(g3.result, g3result, 'g3 failed');
  
  // $avg, and averaging in a final projection
  var g4 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$project: {author: 1, tags: 1, pageViews: 1}},
          {$unwind: "$tags"},
          {
            $group: {
                _id: {tags: "$tags"},
                docsByTag: {$sum: 1},
                viewsByTag: {$sum: "$pageViews"},
                avgByTag: {$avg: "$pageViews"},
            }
          },
          {$sort: {'_id': 1}}
      ]
  });
  
  var g4result = [
      {"_id": {"tags": "filthy"}, "docsByTag": 1, "viewsByTag": 6, "avgByTag": 6},
      {"_id": {"tags": "fun"}, "docsByTag": 3, "viewsByTag": 17, "avgByTag": 5.666666666666667},
      {"_id": {"tags": "good"}, "docsByTag": 1, "viewsByTag": 5, "avgByTag": 5},
      {"_id": {"tags": "nasty"}, "docsByTag": 2, "viewsByTag": 13, "avgByTag": 6.5}
  ];
  
  assert.docEq(g4.result, g4result, 'g4 failed');
  
  // $addToSet as an accumulator; can pivot data
  var g5 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {
            $project: {
                author: 1,
                tags: 1,
            }
          },
          {$unwind: "$tags"},
          {$group: {_id: {tags: "$tags"}, authors: {$addToSet: "$author"}}},
          {$sort: {'_id': 1}}
      ]
  });
  
  // $addToSet doesn't guarantee order so we shouldn't test for it.
  g5.result.forEach(function(obj) {
      obj.authors.sort();
  });
  
  var g5result = [
      {"_id": {"tags": "filthy"}, "authors": ["jane"]},
      {"_id": {"tags": "fun"}, "authors": ["bob", "dave", ]},
      {"_id": {"tags": "good"}, "authors": ["bob"]},
      {"_id": {"tags": "nasty"}, "authors": ["dave", "jane", ]}
  ];
  
  assert.docEq(g5.result, g5result, 'g5 failed');
  
  // $first and $last accumulators, constant _id
  var g6 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$sort: {author: -1}},
          {
            $group: {
                _id: "authors",                  /* constant string, *not* a field reference */
                firstAuthor: {$last: "$author"}, /* note reverse sort above */
                lastAuthor: {$first: "$author"}, /* note reverse sort above */
                count: {$sum: 1}
            }
          }
      ]
  });
  
  var g6result = [{"_id": "authors", firstAuthor: "bob", lastAuthor: "jane", count: 3}];
  
  // Test unwind on an unused field
  var g7 = db.runCommand({
      aggregate: "article",
      pipeline: [
          {$unwind: '$tags'},
          {
            $group: {
                _id: "tag_count", /* constant string, *not* a field reference */
                count: {$sum: 1}
            }
          }
      ]
  });
  assert.eq(g7.result[0].count, 7);
  