How to show data from mongoDB with ObjectID - mongodb

i have an "back end" application which write in MongoDb (in database i have _id: with ObjectId("13f6ea...002")) i use meteor app to show information. Everything was good i displays list of information with {{#each}}. But when i wanted show one element with '_Id' nothing works.
I read this issue and adapt my code to get right root, But i can't display anything on the page. I tried to write Template helpers but it didn't helped
Db record:
{
_id: ObjectId("13f6ea...002"),
url: "foo",
title: "bar",
published: "2014-08-22 03:26:21 UTC",
image: "foo.jpg",
summary: "foo ",
categories: [
"F",
"B"
],
...
}
Route:
this.route('news', {
path: '/news/:_id',
template: 'news',
waitOn: function () {
var id = this._id;
Meteor.subscribe('news', id);
},
data: function() {
var id = this.params._id;
return News.findOne({ _id: Meteor.Collection.ObjectID(this.params._id)});
},
action : function () {this.render();},
});
Publish
Meteor.publish('news', function(id) {
return News.find({_id: id});
});
Template which redirect to unique post
<h4>{{title}}</h4>
And template is just {{news}}
How can i fix this?
UPDATE
My solutions to fix that:
router.js
waitOn: function () {
var id = this._id;
Meteor.subscribe('News', id);
},
data: function() {
return News.findOne(new Meteor.Collection.ObjectID(this.params._id));
},
and in template
<a href="news/{{_id._str}}">

Navigate to the appropriate url in your browser (i.e. localhost:3000/news/[_id]), open the console and enter:
Router.current().data()
That will show you the data context of the current route. Either it returns nothing, in which case there is a fundamental problem with your News.findOne query as it's returning nothing, or (more likely) it returns the required document.
In the latter case, as far as I can see there is no news property within that document, which is why it isn't rendering anything. If you change {{news}} to {{url}} or {{summary}} I would imagine it would render the requested property.
If by {{news}} you're trying to render the entire document, then (aside from the fact that it will render as something like [Object]) you need to make news a property of the object returned by your data function:
return {
news: News.findOne({ _id: Meteor.Collection.ObjectID(this.params._id)});
};

Getting Document with _id :
In the .js file under events, Say on click event and Collection EventList :-
'Submit form' : function () {
var id = this._id;
return EventList.find({_id : id}).fetch();
}
This would return the object for the id. In my Case, I am displaying a field for all documents in Collection. User selects a record and clicks Submit, which fetches all Document fields and displays to the User

Related

How to subscribe to certain records in collection with id in meteor

I'm new to meteor,I have two collections named Employee and Visitors.and two templates Home and Print. i can get the id of the record from the button like this.
printVisitor:function(){
return Visitor.findOne({_id:Session.get('UpdateVisitorId')});
}
now when i click button that redirects to another page and i need to print those values say name, phone number using the particular id of record which i could get from the above code.
my route code looks like this
Router.route('/print/:_id', {
name: 'print',
controller: 'PrintController',
action: 'action',
where: 'client'
});
and my print html is this
<template name="Print">
This is: {{VisitorName}}
Visiting:{{EmployeeName}}
Phone:{{PhoneNumber}}
how can i publish and subscribe and print those certain values of that id
Publish and subscribe can take arguments. You also want to use this.params to get the URL parameters. This is the general pattern
Router.route('/foo/:_id', {
name: 'foo',
waitOn: function(){
// this grabs the ID from the URL
var someId = this.params._id;
// this subscribes to myPublication while sending in the ID as a parameter to the publication function
return [
Meteor.subscribe('myPublication', someId)
]
}
});
/server/publications.js
Meteor.publish('myPublication', function(id){
check(id, String);
return MyCollection.findOne({_id: id});
});
You'll now have access to the data you subscribed to on this route.

Meteor & Iron: Using tag from array as path

I'm using Iron Router for Meteor and I have these routes set up and working so far:
Router.map(function () {
this.route('home', {
path: '/',
template: 'home'
});
this.route('userProfile', {
path: '/user/:username',
data: function () {
return Meteor.users.findOne({username: this.params.username})},
template: 'userProfile'
});
this.route('postPage', {
path: '/post/:_id',
data: function () {
return Posts.findOne({_id: this.params._id})},
template: 'postPage'
});
this.route('settings', {
path: '/settings',
template: 'settings'
});
});
I'd like to introduce another route that would take you to a page where posts are organised by tag. For example http://foo.bar/tag/mexican would take you to a page displaying all the posts that have the tag mexican in an array. The posts are stored in the collection like so:
{
"_id" : "G6xrPYedPzG8KGBTF",
"title" : "Chilli Con Carne",
"rating" : 4,
"tags" : [ "kidneybeans", "mexican", "rice" ],
"description" : "A meaty mexican dish with rice.",
"createdAt" : ISODate("2015-02-15T23:45:12.384Z"),
"owner" : "vh7DjWM9NwbkGSNg9",
"username" : "snowingjack"
}
I've been able to make routes that pass data by post._id as you can see, but now I can't figure out how to make a route where /tag/:tag would take me to page with the data is the posts collection queried by tag. I'm fine running a query that will just return posts with a certain tag like return Posts.find({tags: "mexican"}); but I'm struggling with how to pass all this data around to get the desired effect.
Ideas?
P.S. I also have a template I use to spit out tags in a sane fashion with hashtags and spaces and links and whatnot. I'd love to be able to find a solution where this would work:
<template name="tagListItem">
<span class="tag-list__item">#{{this}}</span>
</template>
I think the route would look something like this:
this.route('tagPage', {
path: '/tags/:tag',
data: function () {
return Posts.find({tags: this.params.tag)},
template: 'tagPage'
});
And the anchor tag inside the template you use to output tag links would probably look like this ( though I'm not exactly sure the data context of the template you mentioned in your post):
#{{this}}
The other thing you would have to consider is how you are publishing and subscribing to posts. You might want to make a separate pub/sub relationship for tags so you are sending posts with tags you don't need down the line.

Updating a record and then displaying it in iron router function

I've got the following iron-router setup with meteor:
Router.map(function() {
this.route('decoded', {
path: '/id/:id',
data: function() {
message.update({_id: this.params.id._id}, {$set: {read: "1"}});
return message.findOne({id: this.params.id});
}
});
Take note that I am storing an id, which is not the same as _id that mongodb generates.
In my template I have {{subject}}
On insert, the value of read is 0, when they visit the url /id/:id I want the value of read to be changed to 1, and then display the subject.
When I run it, I don't get any errors or anything. It displays my message, just fine, but doesn't update the read field.

How to read a collection that depends on another one in Meteor

I'm trying to load the latest post from a collection and at the same time all of the comments of that same post. The collection have references instead of storing the whole documents inside each other:
Post { title, body, etc..}
Comment { postId, body, etc.. }
I'm using iron-router as the routing package and in the route of my page I'm subscribing with this way:
this.route('home', {
path: '/',
template: 'home',
waitOn: function () {
return [
Meteor.subscribe('latestPost'),
Meteor.subscribe('lastReadPost')
];
}
});
The code that retrieves the post is simply:
Posts.findOne({}, {sort:{createdAt:-1, limit:1}});
Now the problem is that I don't know how to retrieve the comments without reading the whole collection. I can't subscribe in the router as I still do not have the post ID to query the Comments collection.
I guessed I could do that from the Template, but of course if I query the Comments collection, it's still empty. But I do have the postId as it's inside the Posts collection at that time. But I would need to trigger a subscription from the Template and that doesn't sound like a clean solution.
What would the best practice be? Thanks!
Server side code:
Meteor.publish("latestPost", function () {
var post = Posts.find({}, {sort:{created:-1}}).fetch()[0];
console.log("publish : " + post.title);
return [
Posts.find({_id: post._id}),
Comments.find({postId: post._id})
];
});
Client side code:
this.route('home', {
path: '/',
template: 'home',
waitOn: function () {
return [
Meteor.subscribe('latestPost')
];
},
data:function(){
return {
post:Posts.findOne(),
comments:Comments.find()
};
}
});
Check this repository to see whole example.
After user changes to another route, then subcriptions are being automatically stopped.
I would also include a limit in the server side finder options
{sort : {created : -1}, limit : 1}

How do I use new Meteor.Collection.ObjectID() in my mongo queries with meteor?

I have a Collection that has documents with an array of nested objects.
Here is fixture code to populate the database:
if (Parents.find().count() == 0) {
var parentId = Parents.insert({
name: "Parent One"
});
Children.insert({
parent: parentId,
fields: [
{
_id: new Meteor.Collection.ObjectID(),
position: 3,
name: "three"
},
{
_id: new Meteor.Collection.ObjectID(),
position: 1,
name: "one"
},
{
_id: new Meteor.Collection.ObjectID(),
position: 2,
name: "two"
},
]
});
}
You might be asking yourself, why do I even need an ObjectID when I can just update based off of the names. This is a simplified example to a much more complex schema that I'm currently working on and the the nested object are going to be created dynamically, the ObjectID's are definitely going to be necessary to make this work.
Basically, I need a way to save those nested objects with a unique ID and be able to update the fields by their _id.
Here is my Method, and the call I'm making from the browser console:
Meteor.methods({
upChild: function( options ) {
console.log(new Meteor.Collection.ObjectID());
Children.update({_id: options._id, "fields._id": options.fieldId }, {$set: {"fields.$.position": options.position}}, function(error){
if(error) {
console.log(error);
} else {
console.log("success");
}
});
}
});
My call from the console:
Meteor.call('upChild', {
_id: "5NuiSNQdNcZwau92M",
fieldId: "9b93aa1ef3868d762b84d2f2",
position: 1
});
And here is a screenshot of the html where I'm rendering all of the data for the Parents and Children collections:
Just an observation, as I was looking how generate unique IDs client side for a similar reason. I found calling new Meteor.Collection.ObjectID() was returning a object in the form 'ObjectID("abc...")'. By assigning Meteor.Collection.ObjectID()._str to _id, I got string as 'abc...' instead, which is what I wanted.
I hope this helps, and I'd be curious to know if anyone has a better way of handling this?
Jason
Avoid using the _str because it can change in the future. Use this:
new Meteor.Collection.ObjectID().toHexString() or
new Meteor.Collection.ObjectID().valueOf()
You can also use the official random package:
Random.id()