[Solved] rawCollection aggregate; TypeError: Cannot read property 'name' of undefined

#1

Hi,

I am trying to implement the excellent suggestions by Rob Fallows for aggregations (Meteor Aggregate not showing correct results).

However, I get the following error:

err TypeError: Cannot read property 'name' of undefined
    at Collection.aggregate (/home/george/.meteor/packages/npm-mongo/.3.1.1.v3rpzk.m5kk8++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb/lib/collection.js:1738:39)
    at Promise.asyncApply (imports/startup/server/aggregate.js:12:36)
    at /home/george/.meteor/packages/promise/.0.11.2.1gwulfb.vjny++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:u5408:

I created a meteor (1.8) project with: meteor create --bare test

on the server I have the following files:
====== index.js ====

import './api';

====== api.js=====

import './Nodes';
import './populate';
import './aggregate';

==== Nodes.js ====

import {Mongo} from 'meteor/mongo';

const Nodes = new Mongo.Collection('Nodes');
Nodes.aggregate = Nodes.rawCollection().aggregate; // define an aggregate method;

export default Nodes;

==== populate.js =====

import Nodes from './Nodes';

for (let i = 0; i <= 100; i += 1) {
  Nodes.insert({prop1: 'test', val: i});
}

==== aggregate.js =====

import Nodes from './Nodes';

const mypipeline = [
  {
    $match: {prop1: 'test'}
  },
  {
    $sort: {val: -1}
  }
];

const testfunc = async pipeline => Nodes.aggregate(pipeline).toArray();

testfunc(mypipeline)
  .then(docs => {
    console.log('docs>', docs);
  })
  .catch(err => {
    console.log('err', err);
  });

If I do a console.log(Nodes.aggregate) I get a function which has the following line:

  // Build the command
  const command = { aggregate: this.s.name, pipeline: pipeline };

So it looks like ‘this.s’ does not exist for some reason.

Any advice as to where I am going wrong would be appreciated.

#2

I’m guessing that this line means that the aggregate function has lost it’s original context and so this doesn’t point to the right place anymore.

Does it work if you change testFunc to this?

const testfunc = async pipeline => Nodes.rawCollection().aggregate(pipeline).toArray();

As an example of what I mean you can try this:

const obj = {
    name: 'Fred',
    hello: function () {
        return this.name;
    }
}
console.log(obj.hello())
// logs 'Fred'
const func = obj.hello;
console.log(func())
// logs undefined
#3

The same error is thrown if I try your testFunc:

const testfunc = async pipeline => Nodes.rawCollection().aggregate(pipeline).toArray();
#4

This may be my bad. Try binding the method to its original context:

Nodes.aggregate = Nodes.rawCollection().aggregate.bind(Nodes.rawCollection());
#5

Boom!
Works perfectly!

Thank you Rob!

#6

Sorry about that. Obviously asleep at the wheel.

Original post edited.