New Collection in Mongo fails to insert new data


#1

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”


#2

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


#3

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.


#4

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.


#5

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.


#6

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.


#7

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


#8

Yep :slight_smile:


#9

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?


#10

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);

#11

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.


#12
  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>

#13

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.


#14

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.