1

In my Meteor app, I have a Meteor method that takes the collection as a parameter and tries to run the mongo insert command on that collection to create a new document. The code runs every 10 seconds using setInterval.

Collection is defined:

My_Collection_Name = new Meteor.Collection('my_collection_name');


Server code:
var collection = My_Collection_Name;
var data = [1,2,3,'a','b','c'];
Meteor.call('createDocument', collection, data);


Method:
Meteor.methods({
  createDocument: function(collection, data) {
    collection.insert({
      data: data
    });
  }
});


However, this returns the following error in the console:
I20141030-14:58:06.716(-4)? Exception in setInterval callback: TypeError: Object #<Object> has no method 'insert'

Why doesn't this work? Is it possible to pass in the collection as a parameter? Thank you in advance!

Jon Cursi
  • 3,301
  • 4
  • 27
  • 53

3 Answers3

3

What happens is that you have different collections on the client and on the server (read more at Understanding Meteor publish/subscribe). Relying on the ~private _collection field is risky. What you do want is to indeed pass the collection name as a string to Meteor.call, make sure you have the same variable name on the server for the collection, and look up the collection by its name in the global object on the server:

// on the client:

MyCollection = new Mongo.Collection('record-set-name');  // set server-side by .publish()
Meteor.call('createDocument', 'MyCollection', data);

// on the server:
MyCollection = new Mongo.Collection('collection-name-in-mongo');
Meteor.methods({
  createDocument: function(collectionName, data) {
    global[collectionName].insert({
      data: data
    });
  }
});

This pattern is used by meteor-autocomplete to pass collection names from the client to the server.

Understanding Meteor publish/subscribe explains how the collection name and collection variable name relate in Mongo.

Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
0

After further inspection of the collection object, I noticed that it has a _collection object inside which, in turn, contains the insert, update, etc. functions. Therefore, adjusting the code to the below solves the problem for running Mongo commands against a collection parameter inside a Meteor method:

Meteor.methods({
  createDocument: function(collection, data) {
    collection._collection.insert({
      data: data
    });
  }
});
Jon Cursi
  • 3,301
  • 4
  • 27
  • 53
  • 2
    This needlessly passes and entire object to the server, and assumes the collections are named the same on the client as the publications are on the server. Check [my answer](http://stackoverflow.com/a/26664357/1269037) for the correct solution. – Dan Dascalescu Oct 30 '14 at 22:24
-1

I think here collection variable is taking as a collection name, If you have few collection names you can do it like below in the server methods

Meteor.methods({
  createDocument: function(collection, data) {
    if(collection == "firstcollection")
    {
      firstcollection.insert({
        data: data
      });
   }
   else if(collection == "secondcollection")
    {
      secondcollection.insert({
        data: data
      });
   }
  }
});
Sasikanth
  • 3,045
  • 1
  • 22
  • 45
  • Thanks for your reply. However, my collection variable is not a string, it's an object. So I can't string-check like that, nor do I think it would work trying to insert on a string. – Jon Cursi Oct 30 '14 at 19:26