New Collection in Mongo fails to insert new data

Hello, I am creating a new local database following this tutorial (http://meteortips.com/first-meteor-tutorial/databases-part-1/) but I cannot make it work.

In my main.js file I define a new Mongo Collection: Data = new Mongo.Collection(‘data’);

Then, when I try to insert Data.insert({foo:1234}); I get in console this:

"Data.insert({foo: 1234});
“wcgeCBB2L48i8F9QA"
insert failed: Method ‘/data/insert’ not found
meteor.js:992:11”

What console do you mean? Meteor shell? Browser Console? If its the browser console: Have you exported your collection?

I meant the browser console. I think I have found the issue, which I probably messing with the structure of the project.

I was creating the Collection in the main.js file of the client/main.js folder.

I created another main.js in the root folder of the app app/main.js and this seems to fix it. I am not sure this is safe, is there another way to make it cleaner.

If you want a local (client only) collection, then you should use Data = new Mongo.Collection('data', { connection: null }); in your client code only.

What you’ve done here is add the collection to the server as well. It’s doing that which ensures the data/insert method is created. It also means that a physical collection is being used.

1 Like

Okay, I have made a local collection for now, as I don’t need to save or manipulate any data in the server. I just have this question, is this affecting the way in my client, if I need to make a list to appear and I add the data manually using Data.insert({…}); and have something like this below:

[js]
Template.name.helpers({
‘dataItems’: function(){
return Data.find();
}
});

[html]

    {{#each dataItems}} test {{/each}}

will this be possible to appear any changes in the list, or do I have to insert the data before.

As far as your app is concerned, it’s just another MongoDB collection, except it’s not persistent, so your client will need to insert before it can find anything.

Okay, so I trust making a function to insert the data in the db before whatsoever will do the trick, right?

1 Like

Yep :slight_smile:

1 Like

I have now this in client/main.js (not in root):

Data = new Mongo.Collection('data', { connection: null });

Meteor.startup(function (){
        if(Data.find().count() === 0) {
            console.log("importing data to db");
            var data = json['muons']; //is an array of objects.
            data = data.forEach(items => Data.insert(items));
            console.log(Object(data));
        };
    });

It seems to load the data when I do this

Data.find({}).fetch();

It returns the following:

[…]
0: Object { pt: 0.1, eta: 0.2, phi: 0.4, … }
1: Object { pt: 0.5, eta: -6, phi: -1, … }
length: 2
__proto__: Array []

How can interact now with this, is it possible to get each key and its values separately?

As you’ve discovered, collection.find().fetch() returns an array of all objects selected by the find(). So, you just use any standard array/object processing from there. As an example, to get the phi property of array element 3: console.log(Data.find({}).fetch()[3].phi; - although you probably wouldn’t do that sort of thing in an inline statement. Something like this is more understandable:

const result = Data.find({}).fetch();
console.log(result[3].phi);

Thanks a lot, makes sense, I can manipulate it on an array-ish fashion.
I am trying to iterate the items on the html side so I can get a list with the keys and its corresponind keys like

  • eta: value
  • phi: value
    etc.

So I am doing this following the turorial again, but no appear of anything.

Template.ipsosboard.helpers({
        'dataItems': function(){
            return Data.find().fetch();
        }
    });

HTML

<ul>
    {{#each player}}
        <li>{{this}}: {{this}}</li>
    {{/each}}
</ul>

I am afraid there is a problem with ‘this’ if I had to guess.

  1. In {{#each player}}, player is your helper - in your case, that’s dataItems, so you should be using {{#each dataItems}}.
  2. You haven’t shown your <template name="xxx"> in your HTML. That name must be ipsosboard to match your Blaze template.
  3. You don’t need fetch() in your helper - Blaze understands cursors, so your helper can be written as:
    dataItems() {
      return Data.find();
    }
    
  4. Rewrite your <li> as:
    <li>{{eta}}, {{phi}}</li>
1 Like

Yes, I probably missed to copy the template name in my example. I made this which represents my data in a more appropriate way.

<template name="ipsosboard">
    <ul>
        {{#each dataItems}}
        <li> pt: {{pt}}</li>
        <li> eta: {{eta}}</li>
        <li> phi: {{phi}}</li>
        <li> charge: {{charge}}</li>
        {{/each}}
    </ul>

This somehow returned the multiplication or sum of all values, so I tried the above.
<li>{{eta}}, {{phi}}</li>

Wouldn’t be possible instead of hard-coding pt: to e.g., Object.keys(Data.find({}).fetch()[0])[0] or something like that in case the data will provide another key in the future , so it will add pt {{pt}} programmatically and make it more flexible rather typing each time the keys of the list.

I don’t understand.

You could certainly do that with your helper by using map() and programmatically getting the keys and their values as array elements with something like:

  dataItems() {
    return Data.find().map(obj => {
      return [
        Object.keys(obj).filter(key => {
          return key !== '_id';
        }).map(key => {
          return `${key}: ${obj[key]}`
        })
      ];
    });
  }

Then alter your template to iterate over the sub-arrays.

<template name="ipsosboard">
  <ul>
    {{#each list in dataItems}}
      <li>
        {{#each value in list}}
          <span>{{value}}</span>
        {{/each}}
      </li>
    {{/each}}
  </ul>

But, IMO it’s really obfuscating the whole thing.