Access existing MongoDB collection from meteor app - mongodb

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

Related

Meteor - using snychronised non-persistent / in-memory MongoDB on the server

in a Meteor app, having real-time reactive updates between all connected clients is achieved with writing in collections, publishing and subscribing the right data. In normal case this means also database writes.
But what if I would like to sync particular data which does not need to be persistent and I would like to save the overhead of writing in the database ? Is it possible to use mini-mongo or other in-memory caching on the server by still preserving DDP synchronisation to all clients ?
Example
In my app I have a multiple collapsed threads and I want to show, which users currently expanded particular thread
Viewed by: Mike, Johny, Steven ...
I can store the information in the threads collection or make make a separate viewers collection and publish the information to the clients. But there is actually no meaning in making this information persistent an having the overhead of database writes.
I am confused by the collections documentation. which states:
OPTIONS
connection Object
The server connection that will manage this collection. Uses the default connection if not specified. Pass the return value of calling DDP.connect to specify a different server. Pass null to specify no connection.
and
... when you pass a name, here’s what happens:
...
On the client (and on the server if you specify a connection), a Minimongo instance is created.
But If I create a new collection and pass the option object with conneciton: null
// Creates a new Mongo collections and exports it
export const Presentations = new Mongo.Collection('presentations', {connection: null});
/**
* Publications
*/
if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish(PRESENTATION_BY_MAP_ID, (mapId) => {
check(mapId, nonEmptyString);
return Presentations.find({ matchingMapId: mapId });
});
}
no data is being published to the clients.
TLDR: it's not possible.
There is no magic in Meteor that allow data being synced between clients while the data doesn't transit by the MongoDB database. The whole sync process through publications and subscriptions is triggered by MongoDB writes. Hence, if you don't write to database, you cannot sync data between clients (using the native pub/sub system available in Meteor).
After countless hours of trying everything possible I found a way to what I wanted:
export const Presentations = new Mongo.Collection('presentations', Meteor.isServer ? {connection: null} : {});
I checked the MongoDb and no presentations collection is being created. Also, n every server-restart the collection is empty. There is a small downside on the client, even the collectionHanlde.ready() is truthy the findOne() first returns undefined and is being synced afterwards.
I don't know if this is the right/preferable way, but it was the only one working for me so far. I tried to leave {connection: null} in the client code, but wasn't able to achieve any sync even though I implemented the added/changed/removed methods.
Sadly, I wasn't able to get any further help even in the meteor forum here and here

How to check if a collection has changed?

I've created a JSON API with Express.js, Mongoose and MongoDB. Currently, there's no way for the clients of the API to check if the data in a collection has changed - they would need to download the whole collection periodically.
How could I allow the clients of the API to check for changes to a collections (inserts, updates, deletions) without downloading the collection itself?
Is there a way of getting the version number of the collection, the last change timestamp or a hash of the collection with Mongoose? What is the best practice solution to this problem?
In current and earlier versions of MongoDB, you have to do it on the application side, maybe using polling.
MongoDB 3.6 has a brand new feature called change stream that allows you to listen changes happening on your collections in real time.
The sample code to listen selected changes happening on your collection is below:
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
MongoClient.connect("mongodb://172.16.0.110:27017/myproject?readConcern=majority").then(function(client){
var db = client.db('myproject')
var changeStreams = db.collection('documents').watch()
changeStreams.on('change', function(change){
console.log(change)
})
})
If you are using node.js, you need to use following node module to get it working:
"dependencies": {
"mongodb": "mongodb/node-mongodb-native#3.0.0"
}

how meteor match subscription with client collection?

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.

How to connect a Meteor site to an existing db & collection?

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

Access to collection from client folder

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)