Meteorjs display referenced document field - mongodb

I have the following scenario. There is a collection Suppliers and another Invited. Now Invited.supplier = Supplier._id (syntax might be wrong) Invited collection refers to Suppliers in One to Many fashion.
In my html , I have
<template name="mytemplate">
{{#each invited_list}}
{{supplier}}
{{f1}}
{{f2}}
{{/each}}
</template>
I have a helper function
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"});
}
});
I would like to display {{Suppliers.name}} instead of _id in {{supplier}} in my invited_list . What are my options?

You could create a resolver function such as:
Template.mytemplate.helpers({
invited_list : function(){
return resolveSupplierToNames(Invited.find({"something"}).fetch());
}
});
function resolveSupplierToNames(invitedList) {
for (var i=0; i<invitedList.length; i++) {
invitedList[i].supplier = Suppliers.findOne({_id: invitedList[i].supplier}).name;
}
return invitedList;
}
There are generally two options with mongodb, one is the above (manual). The second is to use DBRefs. However I'm not sure meteor supports DBRefs completely yet. As suggested in the mongodb docs theres nothing wrong with doing it manually.
Update
Meteor has since introduced a transform function, you can do something similar like:
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"},{transform:function(doc) {
doc.supplier_name = Suppliers.findOne({_id: doc.supplier_id}).name;
return doc;
});
}
});

Related

Meteor get unique items from a collection

I have a collection Files which contain items with a userId. I want a unique array with all userIds in the collection.
Here my first approach (code from here: LINK)
Server Method
'uniqUser': function(){
const distinct = Meteor.wrapAsync(Files.rawCollection().distinct,Files.rawCollection());
const result = distinct('userId');
console.log(result)
return result
}
Client Call
uniqUser(){
Meteor.call('uniqUser', function(err, data) {
console.log(data);
return data;
});
}
the console.log looks good:
but my view show nothing!? also no errors...
uniqUser:
{{#each uniqUser}}
<p>{{this}}</p>
{{/each}}
I have to use meteor-reactive-method LINK:
uniqUser() {
return ReactiveMethod.call("uniqUser");
}
and eveything is fine!

Creating a data context with a data option in iron-router not working

Whilst using iron router 1.011 with Meteor I created a router which returns a Mongo db cursor to a collection subset using a route parameter; see below:
Router.route('/categories/:slug', function() {
this.render('CategoryShow', {
data: {
category_products: Products.find({
category: this.params.slug
})
}
})
});
This works fine, however I didn’t see this as particularly elegant and decide to pass the options as an object as per the documents; see below.
Router.route('/categories/:slug', {
data: function() {
templateData = {
category_products: Products.find({
category: this.params.slug
})
}
return templateData;
},
name: 'category.show'
});
This does not return any data to the template but I notice that this pattern seem to work find when using findOne() instead of find(). Note that the template is declared as:
<Template name="CategoryShow">
// bla bla
</Template>
Please advise

Meteor template helper mongo call crashing app

I have a Meteor app that has become very unresponsive now that I am trying to use Templates and Template helpers more. I basically have two large collections in MongoDB say collection1 with 1531589 documents and collection2 with 1517397 documents. For each collection, the documents within it adhere to a single schema, i.e. collection1 has it's own schema, and collection2 has it's own schema. Both schemas have only a few properties (~5). In my Meteor code I have taken the following approach
Col1 = new Mongo.Collection('collection1');
Col2 = new Mongo.Collection('collection2');
In publications.js
Meteor.publish('collection1', function() {
if (Roles.userIsInRole(this.userId, 'admin')) {
return Col1.find({"ID": "12345"});
} else {
this.stop();
return;
}
});
Meteor.publish('collection2', function() {
if (Roles.userIsInRole(this.userId, 'admin')) {
return Col2.find({"ID": "12345"});
} else {
this.stop();
return;
}
});
In subscriptions.js
Meteor.subscribe('collection1');
Meteor.subscribe('collection2');
I then have templates that should display data from each collection by means of template helpers, so in essence
<template name="superInfo">
{{#each latestInfo}}
<p>{{latestInfo.prop1}}</p>
<p>{{latestInfo.prop2}}</p>
{{/each}}
</template>
with a template helper
Template.superInfo.helpers({
latestInfo: function() {
return Col1.find({"ID": "12345"}, {
sort: {Date: -1},
limit: 1
});
}
});
I know the fault probably lies with how I am querying/publishing/subscribing and I have read posts like this but I still can't figure out the most efficient way of doing this. Another issue might be how I have configured Mongo locally? I have made sure that there are indexes on each collection for the ID field, but that hasn't helped. Whenever I start my app and browser to the page using these templates it becomes totally unresponsive.
I put a few console.logs in the template helpers and noticed they were getting called quite a lot so that also might be an issue. Any suggestions as to how best to address these issues would be really appreciated.

MeteorJS: Autoform + CollectionFS, associating images from an FS.Collection with Corresponding Mongo.Collection Document?

I'm building a very small Meteor application simply to get a better understanding of Autoform and CollectionFS, and their use together. I currently have everything set up with the following packages:
iron:router, aldeed:autoform, aldeed:collection2, cfs:standard-packages,
cfs:filesystem, cfs:autoform
I have a sample Mongo Collection assigned to "Books" set up with a SimpleSchema attached, with fields from the demo like title and author. The corresponding code for the file upload is:
fileId: {
type: String,
autoform: {
afFieldInput: {
type: "cfs-file",
collection: "images"
}
}
}
The FS.Collection code is:
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images", {path: "~/uploads"})]
});
This is in conjunction to a quickform: {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
The insert is fine, and I can iterate over the documents and display the various fields using spacebars and a helper function called "books", like so:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{/each}}
I can also iterate over images uploaded to the FS.Collection with a helper returning the entire collection called "files," and looping over them like so:
{{#each files}}
<img src="{{this.url}}" />
{{/each}}
The issue I'm having is linking the two together. I want to be able to do something along the lines of:
{{#each books}}
<li>{{title}}, by {{author}} <img src="The-Corresponding-Image}}" /></li>
{{/each}}
Obviously not that exact layout, but I basically just want to be able to print images with their corresponding titles and authors to be able to use autoform with collectionfs for my needs.
I'm stuck trying to retrieve the fileId from a specific document in the Books collection, and then plugging that into an Images.findOne({fileId: fileId}) and linking the two together.
Can anyone point me in the right direction?
I was able to figure it out thanks to Ethaan's guidance. What I had to do was the following:
Autoform Hook:
AutoForm.hooks({
insertBookForm: {
after: {
insert: function(error, result, template) {
insertedFile = Books.findOne(result).fileId;
Images.update({_id: insertedFile}, {$set: {'book': result}});
}
}
}
});
I set a field of 'book' to the _id of the document being inserted (stored in the result parameter) right after it was inserted.
This is my corresponding HTML:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{#with files}}
<img src="{{this.url}}" />
{{/with}}
{{/each}}
And my helpers:
Template.layout.helpers({
books: function () {
return Books.find({});
},
files: function() {
return Images.findOne({book: this._id});
}
});

Meteor .find() from Collection returns [object Object]

Running on Ubuntu
Data.js
//Collections
Database = new Meteor.Collection('data');
if (Meteor.isClient) {
Template.main.data = function () {
var c = Database.find();
return c;
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
data.html
<head>
<title>data</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{data}}
</template>
I inserted into the db using mongo:
> db.Database.insert({title: 'ShouldWork'});
> db.Database.find();
{ "_id" : ObjectId("5296403855ee6e1350b35afb"), "title" : "ShouldWork" }
Yet when I run the site it just returns [object Object]..
There should be autopublish on and insecure,
This has become quite the roadblock for me to clear in learning the framework.
This is expected. This is because the results of .find() are always a cursor and have multiple objects.
You have to decide which one you want or if you want to loop through each one.
1) You want to use one result:
var c = Database.findOne();
or 2) You want to iterate through each one:
{{#each data}}
{{title}}
{{/each}}
Additionally be sure to use the property of {{data}} because {{data}}, even with findOne is still an [Object object]. You should use something like {{data.title}} instead depending on the property you want to use.
How to access data in Mongo DB from html ?
First of all you need to have the Mongo DB instance present in global variable i:e it must be declared in any .js file as below. It is not part of client or server code
Say we create a Collection of Events in one of the js files.
EventList = new Mongo.Collection('Events');
Now, in order to access all the objects from HTML, we would need a Helper function inside client in our .js file. Below is Helper used:-
Template.viewEvent.helpers ({
//NOTE : 'event' is the name of variable from html template
'event' : function () {
//returns list of Objects for all Events
return EventList.find().fetch();
}
'users' : function () {
//returns reference to Document for all users
return UserList.find().fetch();
}
});
Just left to Display content on .html:-
Say EventList Collection has fields Event_Name, Event_Date. Below would be the html template code
<template name="viewEvent">
<h2>View Event</h2>
<!-- Iterate on all Objects fetched by the Helper Class-->
{{#each event}}
{{Event_Name}} : {{Event_Date}}
{{/each}}