Cannot find documents from CSV import

I have imported a CSV file two different ways. First I tried mongoimport using port 3001. Seemed to insert the data, but… Then I tried the code below. The data shows up when I look in meteor mongo, but when I find.fetch it it’s always empty. Files:

lib/projects.js:

export const Projects = new Mongo.Collection('projects');

server/main.js:

import { Meteor } from 'meteor/meteor';
import {Projects} from '../lib/projects.js';

Meteor.startup(() => {
  // code to run on server at startup
    console.log("boo");
    let csv = Assets.getText("projects.csv");
    let rows = Papa.parse(csv).data;
    console.log(rows[0]);
    for (row of rows) {
      // console.log(row);
        let recId = Projects.insert({
            "id": row.id,
            "name": row.name,
            "nickname": row.nickname,
            "notes": row.notes == "null" ? "" : row.notes,
            "first_month": row.first_month,
            "last_month": row.last_month
        });
        console.log(recId);
    }
});

client/main.js:

import {Projects} from '../lib/projects.js';

Template.ProjectList.onCreated(function load() {
  let x = Projects.find({}).fetch();
  console.log(x);
});

x is always empty.

Welcome to the Meteor community!

To help members in reading your code, please edit your post and wrap code blocks between triple-backticks, like this:

```
your
code
here
```

Thanks :slightly_smiling_face:

Where was that instruction? I looked for it. Googled, etc.

Hi Joegilllon, welcome to the forums!

The reason fetch is returning empty is because the client side database is empty when the function runs!

So lets look at why it’s empty and what happens with data flow in a Meteor app:

  1. When the client starts up, the client side version of the database is empty
  2. The client then subscribes to data that the server publishes.
    In a new app this is done automatically by the autopublish package to make prototyping faster
  3. The server receives the subscription request and starts sending the requested data to the client
  4. The client receives the published data and populates the local database

As with all client <-> server communications, this takes a bit of time.

The way to handle this in most cases is with reactivity
Because both Blaze templates and minimongo are natively reactive, you can combine the two to display your list of projects:

// client/main.js
import {Projects} from '../lib/projects.js';

Template.ProjectList.helpers({
    projects: function() {
        return Projects.find();
    }
});

// client/main.html
<ul>
    {{#each project in projects}}
        <li>{{project.name}}</li>
    {{/each}} 
</ul>

You’ll see that this renders the a list with the names of your projects!

Great, but why does it work here and not it in onRendered?

When the page first loads it doesn’t have the data yet. So when fetch is run it correctly says there’s no data. The template will also render an empty list at this point.

Once the data is loaded a short while later, the database alerts the reactive functions using it that it has changed. In our case, that’s the projects helper where we called Projects.find().
This function is re-run and the template re-renders with the new result.

Okay but I just want to log out the results of fetch?

The easiest way to find out when the subscriptions are ready is by by using the onReady callback argument to Meteor.subscribe:

// client/main.js
import {Projects} from '../lib/projects.js';

Template.ProjectList.onRendered(function () {
    // this.subscribe is the same as Meteor subscribe but automatically stops 
    // when the template is unloaded and gives you better loading helpers
    this.subscribe('projects', function () {
        let x = Projects.find({}).fetch();
        console.log(x);
    });
});

// server/main.js
import {Projects} from '../lib/projects.js';

Meteor.publish('projects', function () {
    return Projects.find();
});

Note that we also had to create the corresponding publication in server/main.js for the client to subscribe to.

Works like a charm. Thanks. Terrific explanation as well.