I want to update only the name field, the problem with the code I have is that if I update a document, all the mongo documents are updated.
As I update a document in specific, I must admit that I am new to this mongo so any help I thank you.
Client
updatename.html
<template name="updatename">
<form class="editor-container">
<input class=“save” type="text" id="card" value=“{{name}}”>
<button type="button" class=“save” id="save">save</button>
</form>
</template>
updatename.js
Template.updatename.events({
'click .save’: function (e, t) {
e.preventDefault();
FlowRouter.watchPathChange();
var name = FlowRouter.current().params._id;
var name = $('#card').val();
Meteor.call('name.update',name);
FlowRouter.go('/');
}
});
Server
name.js
Meteor.methods({
'name.update'( name) {
Name.update({
Name.update({},{ $set: { nam: name }},{multi:true})
});
}
});
I recommend few improvisations over your Meteor code.
Atleast use Title Case/ CamelCase for better readability of the template name and Meteor Methods for other developer.
use submit .formClassName instead of using click .save, also specifiy parameter name with sincerity like function (event, template)
When you updating document for logged user and not other user, as dmayo mentioned in the code use Name.update({_id: Meteor.userId()},{ $set: {nam: name}}), but there is no sense of specifying { multi: true } when you know that there is going to be only 1 record when you are updating. You can use { multi: true } when you desire to impact many records based on criteria that are definitely going to return more than 1 record.
use check(name, String) in Meteor.method call to ensure what you are sending to the server is eligible for further operations.
Use aldeed autoforms when you know there is no out of the box implementation and is going to be simple.
Below is the improvised code for better readability and up to standards
Client
update-name.html
<template name="UpdateName">
<form class="editorContainerForm">
<input type="text" id="card" value=“{{name}}”>
<button type="submit">Save</button>
</form>
</template>
update-name.js
Template.UpdateName.events({
'submit .editorContainerForm’: function (event, template) {
event.preventDefault();
FlowRouter.watchPathChange();
var name = FlowRouter.current().params._id;
var name = $('#card').val();
Meteor.call('updateName',name, function(error, response){
if(error){
// Show some BERT ERROR message for better user experience
// use "meteor add themeteorchef:bert" to add package
} else {
// Show some BERT SUCCESS message for better user experience
});
FlowRouter.go('/');
}
});
Server
name.js
Meteor.methods({
updateName( name ) {
check(name, String);
Name.update({ _id: Meteor.userId },{ $set: { name: name }});
// Use below code only if you know there can be multiple records for same ID
// Name.update({ _id: Meteor.userId },{ $set: { name: name }}, { multi: true });
}
});
In your name.js file (on the server) your mongo query is empty, so when mongo queries your database, it matches all of the documents/records.
Name.update(query, changes, options)
That is the format per the mongo docs. You need to have a unique identifier. Your form is saving a "name", and that's what you are passing to the Meteor.method, but you're not telling the method who's changing their name. If the user is logged in, then you can just use the meteor unique id Meteor.userId()
Name.update({_id: Meteor.userId()},{ $set: {nam: name}},{multi:true})
Also, your option multi:true says to update any and all documents that match the query. If in your original method as written, you had multi:false (the default) then only one document would have been updated (but probably not the one you wanted as the first match would have been updated because of your empty query field.
Mongo docs: https://docs.mongodb.com/manual/reference/method/db.collection.update/
Metor docs: https://docs.meteor.com/api/collections.html#Mongo-Collection-update
Related
I created a collection called Stampest that stores a reference of an uploaded image and a title string, created by a user. Using the ostrio:autoform package.This package creates a collection called Images where all the user uploaded images are stored and hense referenced to/from.
When I query mongo in my terminal using
db.stampest.find({})
I get the entries
Which shows that there are documents in the database, in the Stampest Collection. But the PROBLEM is that when I look at the collection in Meteor Toys debug, it says its empty, and when I insert a document, in this case, the image and the title, the collection changes to 1 for a split second and geos back to 0. There are no error from the terminal or console
As a consequence, I cannot access these documents, what can I do?
This is the schema.js
Schemas = {};
Stampest = new Meteor.Collection('stampest');
Stampest.allow({
insert: function (userId, doc) {
return userId;
},
update: function (userId, doc, fields, modifier) {
// can only change your own documents
return doc.userId === userId;
},
remove: function (userId, doc) {
// can only remove your own documents
return doc.userId === userId;
}
});
Schemas.Stampest = new SimpleSchema({
title: {
type: String,
max: 60
},
picture: {
type: String,
autoform: {
afFieldInput: {
type: 'fileUpload',
collection: 'Images',
// uploadTemplate: 'uploadField' // <- Optional
// previewTemplate: 'uploadPreview' // <- Optional
}
}
}
});
Stampest.attachSchema(Schemas.Stampest);
The publish is like this:
Meteor.publish('stampest', function () {
return Stampest.find({author: this.userId}).fetch();
console.log(Stampest.find());
});
The user inserts the image and the title like this:
<template name="createStamp">
<div class="grid-block">
<div class="grid-container">
<div class="upload-img">
{{file.original.name}}
</div>
<div class="new-stamp-container">
{{> quickForm collection="Stampest" type="insert" id="insertStampForm" class="new-stamp-form"}}
</div>
</div>
</div>
</template>
From what I see in your code, you are returning an Array of db items and not a Cursor in your code.
If you take a look at https://docs.meteor.com/api/pubsub.html, you'll notice that regular publications return simple cursors or array of cursors but never your fetched data.
edit: also, the console.log in your publication will never be interpreted as it returns on the previous line.
I'm trying to get return a list of users based on their accountActiveDate which is stored in a separate collection. If I console.log candidateUserIDByDate it returns the users in the correct order however when I return Meteor.users.find using the var candidateUserIDByDate its not sorted.
Path: sort.js
let sortCandidatesByDate = CandidateAccountStatus.find({}, {sort: {accountActiveDate: 1}}).fetch();
let candidateUserIDByDate = _.map(sortCandidatesByDate, function(obj) {
return obj.candidateUserId;
});
return Meteor.users.find({$and: [{_id: { $ne: Meteor.userId() }}, {_id: { $in: candidateUserIDByDate }}]});
I think a (probably hackish) solution would be, returning the CandidateAccountStatus and inside the loop, using another helper to return the correct user like this:
Template helpers:
status: function(){
//you might want to do {$ne: {Meteor.userId()}} for the correct field
//in your selector if you don't want currentUser status
return CandidateAccountStatus.find({}, {sort: {accountActiveDate: 1}})
},
statusUser: function(){
//change correctField to how you save the userId to
//your CandidateAccountStatus schema
return Meteor.users.findOne({_id: this.correctField})
}
HTML
{{#each status}}
{{#with statusUser}}
<!-- You have the user object here -->
{{_id}} <!-- gives the userId -->
{{/with}}
{{/each}}
Probably a bad title, I don't know how to precisely describe this.
Template.body.helpers({
messages: function () {
return Messages.find({}, {
sort: {createdAt: -1}
});
}
});
This is the code I have.
On the client side, it takes
{{#each messages}}
<span class="text"> {{messageText}} </span>
{{/each}}
Each message contains "text" and "username".
How would I go about, in the "return Messages" part, modifying what it returns?
So I would do something like
Template.body.helpers({
messages: function () {
Messages.find().forEach(function(thismsg){
messageText = slugify(thismsg.messageText)
};
}
});
Get messages, modify the fields and then return them. Could I perhaps do this in subscriptions instead? Please help.
You can pass your message in the helper and then you can modify the message and pass back to the template like this.
Your template code.
{{#each messages}}
<span class="text"> {{slugifyMessage text}} </span>
{{/each}}
You helper code.
Template.body.helpers({
messages: function () {
return Messages.find({}, {
sort: {createdAt: -1}
});
}
slugifyMessage: function(messageText){
return slugify(messageText);
}
});
Please make sure your text that I am passing to slugifyMessage will same name as database you mentioned that you have only two field named username and text, So I took text you can replace this with your doc field that you want to modify.
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.
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