I have server & client files and am trying to send some data to Javascript rather than into a template. In the template, I can output some values, but I need it in JS to add markers to Leaflet.
I guess, there's no sense to funnel the data through templates to get it into JS and into Leaflet, right?
What am I doing wrong?
shell
$ mongo
MongoDB shell version: 2.4.9
connecting to: test
> use atms
switched to db atms
> db.markers.count()
1868
Running the server:
$ MONGO_URL=mongodb://127.0.0.1:27017/atms meteor
lib/collections.js
Markers = new Meteor.Collection('markers');
In the client/client.js, I try to get records from the collection, but it's empty:
Template.hello.helpers({
marks: function () {
// this data renders correctly on map
return Markers.findOne({})
}
});
Template.hello.onRendered(function() {
// this data is empty in console
var query = Markers.find().fetch();
console.log(query);
});
In the template, it shows one record, which means the connection works. But console output is [].
The main problem is you have 2 different Markers collection on client and server. So, on the client, meteor accesses client Marker collections and does not show any data. Collection definition should be shared between client and server, not duplicated.
Make a folder lib and put the collection definitions there
//lib/collections.js
Markers = new Mongo.Collection('markers')
And remove the collection definitions in both server and client folder.
Also, be aware that when you use the separated mongo instance, the reactivity will happen quite slow (2 or 3 times compared to the embedded mongo)
Pretty sure this is answered here:
Using Multiple Mongodb Databases with Meteor.js
Just a note on the syntax, in ver 1.2.1 you want to declare your Meteor collection as a global variable so it can be accessed outside of the file you type it into. Also, you want to put this line in /lib or a directory that can be accessed by both the client and server.
Markers = new Mongo.Collection('markers')
Related
I want to publish a sever side collection to the client side.
In Server Side
MedicalCenters = new Mongo.Collection('medicalCenters');
Meteor.publish('medicalCenters',function () {
return MedicalCenters.find({});
});
I want this collection only to be accessed by a particular template. Thefore,
In Client Side
Template.doctor.onCreated(function () {
Meteor.subscribe('medicalCenters');
});
Now I can pass the data from client side template and even write to the serve side collection. But it seems to be subscription did not work and therefore, I cannot display collection data in the template.
(The collection is not displayed in the meteortoys Mongol)
How do I fix this?
It sounds like you have not placed your collection definition code in a common location that is executed by both the client and server. I'm making this assumption because you said that the collection itself was not visible in mongol.
Remember that in order for publish/subscribe to work, collections must exist on both the client side (using minimongo) and the server side (using mongodb).
Refer to the Meteor Application Structure guide for the details, but essentially you should put your collection definition code in a file that is not within a special directory (e.g. the server/ or client/ folder). Doing so ensures that the code is executed by both the client and server (per the meteor api docs).
All JavaScript files outside special directories are loaded on both the client and the server.
In the older meteor days (before we had the imports/ folder) people often placed their collection definition code inside a lib/ folder within the meteor project root. Now it's common for it to be within the import/api/ directory as described here.
Try adding a helper to send the data to the template:
Template.doctor.helpers({
medicalcenters() {
return MedicalCenters.find();
}
});
Then in your template you can loop through the medical centers
<template name="doctor">
{{#each medicalcenters}}
{{name}}
{{/each}}
</template>
on meteor server side, this looks fine, which maps server side collection to publication
if (Meteor.isServer) { // This code only runs on the server
Meteor.publish('tasks', function tasksPublication() { return Tasks.find(); }); }
and the following on the client side is also understandable, which maps subscription to publication by name.
Meteor.subscribe('tasks');
But I couldn't find in any tutorial or docs explaining how subscription and client side collections are mapped to each other. There is no code mapping tasks (subscription) to Tasks (client side collection). Meteor might assume the client collection uses the same name as the server side by both including the same collection declaration (Tasks = new Mongo.collection('Tasks');). But what if I want to use a different collection name on the client side? or what if the info sent by the server is a mix of fields from multiple collections, how do clients know which collections to store this info when they get it from subscription?
This is part of the way Meteor works. It automatically synchronises data in collections between client and server. You don't need to worry about it, and you can't change it.
Your helper methods can pull data from different server collections, and put the data in arrays - you can read from different collections to do this, and you can do it reactively, so when the source collection changes it will run your helper again.
You can also define client only collections, which don't get saved to the server.
So you can probably do what you want, and if you then want to save something from your smooshed data, you would probably write a piece of code to extract the data to be updated into an object, and then save that.
Lets breakdown the code:
Meteor.publish('tasks', function() {
return Tasks.find();
});
Here we have defined a publication name 'tasks' which supplied data it has received from the function return Tasks.find().
Similarly, when subscribing, we refer to that particular publication- tasks in this case and we get those data.
Now coming to the part of linking it to the collection. In Meteor, when you define a collection, it should be defined on both client and server. So when you define a collection like Tasks = new Mongo.collection('tasklists');, On server, the Tasks object refers to the collection tasklists that the server will use to communicate with the mongoDB server. On the client, an object with the name Tasks is created to interact with the database minimongo created in client for tasklists. The Minimongo is a client side API in JS for MongoDB. (You can consider it as a client side replica of the mongoDB database).
So, on client side, you can define Tasks as anything as long as it is an object for the mongoDB collection tasklists- e.g AnyName=new Mongo.collection('tasklists');
Regarding how publication and subscription will know, which collection are we talking about: Publications send across something known as cursor which is related to a particular document(s) and collection in 'mongoDB'. As long as you get the collection name( tasklists) correct, you can have different object names(Tasks) on client and server.
In my MongoDB, I have a collection that I created and populated from the server side, called "fs.files" (It's a gridFS collection).
In my meteor app, is there a way to declare a global variable that simply can fetch me information from this database?
I tried
PDFs = new Mongo.Collection("fs.files");
PDFs = new FS.Collection("fs.files", {
stores: [new FS.Store.FileSystem("fsfiles", {path: "./reports"})]
});
Both of them would return an empty array when I do PDFs.find().fetch()
The problem is, I do not want to create a new collection. I simply want to have access to an existing one since I do not create this database from client side.
Your approach should work. You are likely forgetting to publish this collection on the server and subscribe to it on the client.
server:
Meteor.publish('myPDFs',function(){
return PDFs.find();
});
client:
Meteor.subscribe('myPDFs');
Hi im getting started with meteor, so i have a problem: I can't access to collection from client folder
my project struct is default: meteor create testApp
/testApp
--.Meteor/
--testApp.html
--testApp.css
--testApp.js
then i create a mongo collection i add it to testApp.js
city = new Mongo.Collection('data');
running the app with meteor command, then i access to chrome console
city.find().fetch(); it work perfect and it return the cities
but when i move testApp.js , testApp.css , testApp.html to new folder named /client
/testApp
--.Meteor/
--client/
----testApp.html
----testApp.css
----testApp.js
i cant get the collection from chrome console it mean city.find().fetch(); return []
any idea ?
This is normal behavior. client and server are considered special folders by meteor, where respectively only the client or the server will execute the code that they contain. It is the equivalent of an implicit if (Meteor.isServer)
When you declare a collection in the client folder only, it will only create an empty collection in your client-side database, MiniMongo. Therefore, your MiniMongo collection has no link to any server-side, "real" mongodb collection. That is why you cannot access the data saved into your actual mongodb database.
So in order to fix this, what you can do is either:
declare your collection once in a separate js file, outside of your client and server folders so that both sides are aware of that collection (recommended in most cases). I use a collections folder at the root of my app for that
declare your collection twice : once in your client folder like you did, and another time in the server folder at the root of your app (useful in specific cases such as capped collections, etc)
Same situation like this question, but with current DerbyJS (version 0.6):
Using imported docs from MongoDB in DerbyJS
I have a MongoDB collection with data that was not saved through my
Derby app. I want to query against that and pull it into my Derby app.
Is this still possible?
The accepted answer there links to a dead link. The newest working link would be this: https://github.com/derbyjs/racer/blob/0.3/lib/descriptor/query/README.md
Which refers to the 0.3 branch for Racer (current master version is 0.6).
What I tried
Searching the internets
The naïve way:
var query = model.query('projects-legacy', { public: true });
model.fetch(query, function() {
query.ref('_page.projects');
})
(doesn't work)
A utility was written for this purpose: https://github.com/share/igor
You may need to modify it to only run against a single collection instead of the whole database, but it essentially goes through every document in the database and modifies it with the necessary livedb metadata and creates a default operation for it as well.
In livedb every collection has a corresponding operations collection, for example profiles will have a profiles_ops collection which holds all the operations for the profiles.
You will have to convert the collection to use it with Racer/livedb because of the metadata on the document itself.
An alternative if you dont want to convert is to use traditional AJAX/REST to get the data from your mongo database and then just put it in your local model. This will not be real-time or synced to the server but it will allow you to drive your templates from data that you dont want to convert for some reason.