I am new to meteor and want to modify database document from the user interface,
I understand that we have to use update function but unable to use it as I want to edit the collection from UI on click command, please suggest how to go about it.
Arguments
selector Mongo Selector, Object ID, or String
Specifies which documents to modify
modifier Mongo Modifier
Specifies how to modify the documents
callback Function
**Optional**. If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.
Please suggest how to use modifier.
Lets put this on an example, using an event handler.
Template.example.events({
'click #updateThis':function(e,t){
var newValue = t.$('.newValue').val(); // taking value from random input
Collection.update({_id:this._id},{$set:{value:newValue}},function(error,result){
if(error){
console.log(error.reason)
}else{
console.log("Nice update")
}
})
}
})
So first the Selector, like it says it should be the ID of the document to modify.
the modifier in this example is the $set more about field update operators here
and the callback is to make it asynchronous, with the 2 parameters i like to use error and result
Related
I have a firebase realtime database trigger on a create node. my need is to update a property based on some condition in the create trigger for the same object. The way i am doing currently is below:
exports.on_order_received_validate_doodle_cash_order = functions.database.ref("/orders/{id}")
.onCreate((change, context) => {
console.log("start of on_order_received_deduct_doodle_cash")
const orderId = context.params.id
const order = change.val();
var db = admin.database();
const orderRef = db.ref('orders/')
return orderRef.child(orderId).update({"_verifiedOrder": true})
})
As you can see i am getting order id from context and then querying object again and updating it. My question is do i need to do this circus or can i just update it without querying again?
Generally it looks good. Just some small feedback to make you feel more confident about being on the right track.
Call the parameter snapshot instead of change because the parameter name change only make sense for the onUpdate event trigger.
You do not need to log that you're entering the function. Because entering and leaving the function is automatically logged by Firebase also.
You can remove the order variable that is unused.
You are actually not "querying" the object again. Making a reference to a node in the database doesn't make any network call itself. Not until you subscribe to receiving data. So doing orderRef.child(orderId) is not a query, it's just a database reference.
You can use the snapshot's own reference attribute to shorten your code a bit... effectively throwing away almost all code :-)
So your code code look like this instead. It is doing the exact same thing, just shorter. It was also correct from the beginning.
exports.on_order_received_validate_doodle_cash_order = functions
.database
.ref("/orders/{id}")
.onCreate((snapshot) => {
return snapshot.ref.child("_verifiedOrder").set(true);
});
But as mentioned in my comment above, you are effectively just setting a flag that is confirming that data was saved (or rather: confirming that the function was triggered). You might want to add some logic in there to check whether the order can be placed or not and then set the verified flag to true or false depending on that. Because with the logic of the implementation, all orders will have the value _verifiedOrder set to true, which is a waste of storage in your database.
I have a restaurant bookmarks list in my firebase, but I don't know how to delete a specific restaurant in my database.
So I have the function unfavorite(favorite) where I pass the favorite restaurant as a parameter. Till here, than I want to pass this parameters id to the query to remove from the database like this:
this.afDb.list(`bookmarks/${user.uid}/restaurant/${favorite.restaurant.id})`).remove();
here is a screenshot of my database list:
How can I remove that specific restaurant out of the bookmarks list?
You will first need to add an ".indexOn": ["id"] rule to your database something like this:
"bookmarks": {
"$user_id": {
// normal reads and write rules here
},
".indexOn": ["id"]
This step is necessary for firebase database because otherwise you wont be able to use the orderByChild() and equalTo() methods.
Then, where you have your delete function, you want to instead use:
exampleRef = yourDb.ref("bookmarks/${user.uid}"); //this is just to simplify your reference a bit
exampleRef.orderByChild('id').equalTo(theDeleteIDhere).once('value').then(snapshot => {
snapshot.forEach((restaurant) => {
restaurant.ref.remove();
});
}); //this is a Promise that you can modify to return "true" if successful for example
The example I provided is just the way I have done it before (i.e. I prefer to use promises; hence the then() becuase this makes it easier to return that promise in an angular service which allows me to check whether the request was successful). You can use any variation of this so long as you have the "indexOn" rule and you use any sort of "sorting" method firebase provides here
Method 2
When I wrote this I totally glanced over the ability to map your restaurants like such:
Lets say your project is already listing those restaurants. You can therefore save each restaurant's auto generated id to a variable or map:
restaurants; // this is a map like this <your-identifier:autoID>
you can then easily just call:
exampleRef.child(restaurants[yourIdentifier]).remove();
How do I retrieve a document single attribute value, by using the document userId?
First I return the document _Id using the following code
Session.set('getUserId', Al.findOne({_id: Session.get('appealId')}));
console.log(Session.get('getUserId').userID);
I can see the userID is printed successfully in the console, now I want to use the userID to retrieve another value from Meteor.users collection.
Here is my code:
Session.set('userDetails', Meteor.users.findOne({_id: Session.get('getUserId').userID}));
console.log(Session.get('userDetails').profile.annualLeave);
but it doesn't seem to work, I get the following error in the console:
TypeError: Cannot read property 'profile' of undefined
I tried to change Session.get('userDetails').profile.annualLeave to Session.get('userDetails').username and I still get the same error telling me that username is undefined
UPDATE :
for the appealId session, I use it to store the _Id of the item from the router. to use it later to retrieve the userID (Attribute inside the item).
Here is the code:
Router.route('/appeal/:_id', function(){
Session.set("appealId", this.params._id);
this.render("navbar", {to:"navbar"});
this.render("appealDetails", {to:"main"});
});
The error message means that
Session.get('userDetails')
is not defined, which in turn means that the call to
Meteor.users.findOne({_id: Session.get('getUserId').userID})
Must have not returned anything
You are not clear how these two pieces of code are related, and your repeated use of Session seems convoluted. I don't even know why this line of code is there
console.log(Session.get('test').userID);
Unless 'test' is something you stored earlier
I'm doing the newbie tutorial 'simple-todo' and noticed that once I added security in step 9, I was no longer able to delete tasks created before that.
The issue is that my remove method is checking to make sure that the ID it receives is a string, and the to-do tasks that were made earlier via the console return an object when I use this_.id.
In other words:
Tasks created via the terminal, this._id -> ObjectId("57a128afbe5fd7e7ba9a6fca")
Tasks created with the Tasks.insert method, this._id -> "57a128afbe5fd7e7ba9a6fca"
And the new remove method doesn't like the ObjectId part. How can I get just the ID? I would figure it'd be something like this._id._id, but that's undefined. The workaround was to remove the check from the "remove" method, which is less secure.
Link: https://www.meteor.com/tutorials/blaze/security-with-methods
You can use this._id._str to get the Hex part of the ObjectId.
I would suggest that your method only uses the string, and do a check in the client to see if you need to use this._id or this._id._str
For security reasons, I want to add and remove properties of documents before publishing them to the client, depending on some dynamic calculations. I follow the Meteor documentation and this other SO question.
For example simplicity, say I try to add the following static property to every document (SERVER SIDE ONLY):
var Docs = new Meteor.Collection('docs', {
transform: function (f) {
console.log('Tagging doc: ' + f._id);
f.myProp = 1;
return f;
}
});
For some strange reason, this does not work:
Only some documents trigger the transform function, not all (I can see this through the console logging)
On the client side, none of the documents are tagged with myProp
I haven't tried to put the transform on both the client and the server, because in my real life app I cannot do the necessary computation on the client.
Transform functions on collections are intended for convenience, not security -- note that when you call observeChanges on a cursor, the information is not passed through the transform function (it is passed through the transform when you call observe). The default way of publishing a cursor works by calling observeChanges on it.
If you want to strip off fields of a cursor you're publishing, use the fields option to find on your collection. If you want to do something more complicated, you can explicitly do whatever computation you need if your publish function calls added, changed, and removed itself, instead of returning a cursor. Check out the docs for Meteor.publish for details.