I have a problem that I can't seem to find a proper solution for.
First of all, I'm using the meanjs framework, which mean I use express, nodejs, mongoose and mongodb in the backend!
The problem goes like this: Every time I want create a post, I attach a user to the post as it's creator, this is done by using the Schema.ObjectId type in mongoose.
When I create a post I want to give the user a point. So the flow would be something like this:
Create post-> post.created-> post.postCreator.points+=1
I wanna implement this logic for more things, such as, if others liked your post, you would also recieve a point. The flow would be something like this for that:
Like post->post.likes+=1->post.postCreator.points+=1
I want this to be done completely in backend but I'am not sure how I would implement this sort of functionality correctly..
In both the examples the post.postCreator is a Schema.ObjectId type, where it references the correct User document.
If someone could point me in the right direction how this should be implemented I would really appreciate it.
Thanks in advance!
If you have the user id from your Post instance, you would then need to query and update the User. Example:
schema.post('save', function(p) {
UserSchema.findByIdAndUpdate({'_id': p.userId}, {$inc: {points: 1}},
function(error, user) {
// do something else with the user if necessary
}
);
});
Related
With mongoose, they very often give documentation in which they create a new document on a model on the spot, and then modify a field and save it, like so:
const Tank = mongoose.model('Tank', yourSchema);
const small = new Tank({ size: 'small' });
small.size = 'big'
small.save()
// saves doc as {size:'big'}
What i want to know is if its possible to use this way of creating a doc and modifying it using mongoose doc methods and operators, for example:
small.update({size:'reallyBig'})
small.save()
//i would expect the document to now be saved with size:'reallyBig', but it doesn't seem to work this way
This example seems useless, but i want to see if this basic principle is possible because i want to use some mongoose operators for more complex calculations and updates of the document, before it is even saved to the databse.
The problem im having is that this doesnt automatically create an ObjectID for the doc, and Document.updateOne() seems to internally use the doc's _Id to find it... but i havent even saved it so im not sure how it's supposed to find it.
I want to be able to use ops like $inc, $count, $addToSet and such, but am i missing something to be able to use these methods to modify the doc before save()?
How, by using the 'findOne'/'find' functions of mongoose, can I find a specific document, where the results are filtered by a virtual field which does not appear physically in the db?
I'll try to further explain:
In my 'User' model, I have a field called 'email'. I want to create an alias for 'email' as 'userkey' for other functions in my nodejs app (mostly login validations and stuff).
To create the alias, I did this:
userSchema.virtual('userkey').get(function()
{
return this.email;
});
Now, after I created the alias, I want to filter my search result the following way:
restApi.post('/login', function (req, res) // (using expressjs)
{
User.findOne({'userkey': req.body.userkey}).exec(..);
}
How can I do this efficiently and without creating any more methods\field etc to save up time and memory?
The alias is very important, because in the future of the app I'll add more ways to login, and I want to be able to quickly switch between fields to be associated with 'userkey'. This alias saves the trouble of changing the entire app (which is a huge programming principle), and can help me to add more logic which is going to be necessary in the future.
You can't.
Virtuals do not exist on the document stored in mongodb, so there's nothing to query on.
OK this should be fairly simple so I think I may be doing a thinking mistake.
I have an existing document. I serve it to the client, together with its ObjectId. The client modifies, and wants to update the document. So it comes with the id - looks to me a good choice to identify which document I want to update (?).
But I get an error:
[MongoError: Mod on _id not allowed]
This is the code which updates (via HTTP PUT):
id = req.body._id
Item.update({'_id': id }, req.body, (err) ->
So you need to remove the _id key from the "update" object you send. _.omit can facilitate this.
Item.update {_id: req.body._id}, _.omit(req.body, '_id'), (err) ->
Aside: I see people code like this often. Taking input from the browser and just shoving it into your database is a terrible idea from a data integrity and security perspective. Just like most businesses don't just leave their accounting ledgers out on the counter with a pen and ask the customers to write in there unsupervised. Consider enforcing your data schema, authorization, and some validations.
I have noticed in Geddy that when I create a model and a subsequent record for that model, I get a very ugly model ID associated with the record. Something like:
http://localhost:4000/posts/3FEEDE8D-2669-445B-AEA1-A31092A7FEDA
Is there a way to change this?
Ideally, I would always want this to be some sort of string. Where it be for a post or user:
http://localhost:4000/posts/this-is-a-post-title
http://localhost:4000/profile/meebix
If this is possible, how should I:
Configure routes
Change primary key for model
Other implementation steps I may need
Thanks!
Yes, you can change the id if you really want to, but you'll be going off the beaten path there, so it's quite a bad idea. Let Geddy handle IDs for you.
The way I would do this (and certainly how many others have too) is to have a "slugging" function create a slug from the post title, and save that in your database. Then, query on that instead in your show action. You won't have to change your routes.
This is what your query will look like in the show action:
Post.first({slug: params.id}, function (err, post) {
params.id is whatever string you use in the route /posts/<this string>
So once you change your show links to use the slug instead of the ID you will be all set!
i have one conceptual question about designing data model in mongo db.
I have some record for "lists". Each list is "one row" record with id, descr, createdBy etc. fiels. But now i have a requirement that each "list" can be shared with other users. What is the best way to design/re-design the model so when user login to see "lists" that he created and "lists" that was shared with him? I was thinking of creating new field "sharedWith" in which all usernames with which "list" is shared to be put separated with comma(or something else). And then when request is made to search in this field. But somehow this approach doesn't seem to me very useful. Can you give me some advice or guidelines ?
I'm using nodejs with mongoose.
Thanks!
User: {
...
myLists: Array<ListObject>
sharedLists: Array<ListObject>
};
ListObject: {
...
owner: User,
sharedWith: Array<User>
};
That would seem a sensible design to me.