Update mongoDB with todolist information? - node.js

I have a todolist feature in my frontend, here is a demo: https://gyazo.com/a10fcd7c470439fe5cc703eef75b437f
It is all updated using an array in a Vue component and then using v-models to keep track of the data and change the UI to reflect that array.
When the user clicks 'send' i want it to send off the data to the database.
The issue im having is that i can't work out how to import newly created 'todos'(the text box and check box that is created when the + button is clicked) into the database.
This is what each todolist document looks like in my 'todolists' collection in the mongo:
{
"_id":"5caca1498accb128c8974d56",
"title":"todolist1 11111 11111 11111 11111",
"userEmail":"test#gmail.com",
"todos":[
{
"_id":"5caca1498accb128c8974d57",
"description":"Get this done",
"completed":true}
],
"dateDue":"2019-04-07T18:24:31.207Z",
"__v":0
}
The 'save' button in the demo has a v-on:click attribute that has a function named saveTodoList(), which then makes an axios post request to the route /updateTodoList
Feel free to ask any questions that will help you answer my question :)

When a new todo is saved after clicking plus button, make a request on /updateTodoList with parent document's _id. So your request might look something like this:
POST /updateTodoList:
Body:
{ "_id": "5caca1498accb128c8974d56",
"todo": {
"description": "This is a newly added todo description",
"completed": false
}
}
Then, on the server side, parse this body object and update the document with matching _id and push the new todo into the document. Your query will look something like this:
todolist.findOneAndUpdate({_id: req.body._id}, { $push: {todos: req.body.todo } })
Hope this helps.
Edit:
Each time you push a todo using above query, mongo inserts that element to the todos array. For pushing multiple todos in single query, use $each operator along with $push. Official documentation here.

Related

MongoDB nested arrays aggregated update array

I need to create a website that on a user click the like button he toggle the like, so if he liked the post the like is removed and if the post doesn't have the like user will like it.
Data structure of database is like this:
{
"_id":"5f9d838caf0d921703818c89",
"page": "nickname",
"posts":[
{
"post": postData,
"likes": ["user1","user3"]
}
]
}
I need a nodejs function to add or remove user name from likes.
Example:
user2 click the like button
the function to give or remove likes know the post index in "posts" so for example index post 0
function check if posts.0.likes contains the like of "user2"
if "user2" is not included in array then include it else remove from array

CouchDb get post author

My post document looks like the following:
{
_id: ...,
type: 'post',
title: ...,
description: ...,
author: 'user_id'
}
And another user document:
{
_id: 'user_id',
type: 'user',
name: ...,
}
How do I fetch the post and the linked user document given that I only know post id?
Having user document inside the post document doesn't seems like a good solution as if the user changes his/her name or other details, I will have to update every post.
Another solution would be to include a posts array in the user document and use two emits in the view document. But with frequent posts and high number of posts, this looks a little inefficient.
You mentioned "linked documents" as if you were referencing this feature in CouchDB, but it doesn't appear like you meant it that way.
It turns out, this is totally supported. Your document structure doesn't need to change at all, you can use a map function like this:
function (doc) {
if (doc.type === 'post') {
emit(doc._id)
emit(doc._id, { _id: doc.author })
}
}
By emitting an object with an _id property as the value, it allows CouchDB to look up a different document (in this case, the user document) than the original when you add include_docs=true on your view query. This allows you to fetch an entire collection of related documents in a single query! I'd reference the documentation I linked to earlier for a complete example. (the rest of their docs are great too!)

Update single field in CouchDB

I want update one field in a document. I created a new document:
And I would like to change the value of field name from aaa to test. I copied a script from: wiki.apache.org/couchdb/Document_Update_Handlers, and I created a new design document:
Next I created a URL:
localhost:5984/asd/_design/temp/_update/in-place-query/8d6257096bbb199a3757954c00000d0c?name=title&value=test
That should update my field. I instead saw the error:
"{"error":"TypeError","reason":"{[{<<\"message\">>,<<\"point is undefined\">>},\n {<<\"fileName\">>,<<\"../share/couchdb/server/main.js\">>},\n {<<\"lineNumber\">>,1500},\n {<<\"stack\">>,\n <<\"(\\\"_design/temp\\\",[object Array],[object Array])#../share/couchdb/server/main.js:1500\\n()#../share/couchdb/server/main.js:1562\\n#../share/couchdb/server/main.js:1573\\n\">>}]}"}"
Have you got any idea to repair it?
Your update handler design doc should be in the form:
{
"_id": "_design/app",
"updates": {
"accumulate": "function (doc, req) { // Your code here }"
}
}
For further information, please checkout this SO post.
Let me know if this helps !

Mongo DB Document only returns with "_id" that has "$oid"

I'm trying a very simple CRUD API with the MEAN stack. I entered several documents into a mongolab sandbox db. I could do a GET on all documents and they would all be returned. Then I tested GET by ID:
router.route('/api/v1/resources/:resource_id')
// get the resource with that id (accessed at GET http://localhost:8080/api/resources/:resource_id)
.get(function(req, res) {
Resource.findById(req.params.resource_id, function(err, resources) {
if (err)
res.send(err);
res.json(resources);
});
});
And it simply wouldn't work. I kept getting null. But the document existed. I could see it when I would do a GET on all documents.
Then I got another document to return, finally.
The difference? The record that returned had an id in this format:
{
"_id": { "$oid":"1234567890abc"}
}
But records that did not return had this:
{
"_id": "1234567890abc"
}
Can Anyone explain this to me? I entered the data with Postman and I didn't do anything different between the entries.
What is $oid?
What creates the $oid?
Why does that nesting matter for mongoose's findById()?
Thanks!
$oid is from Strict MongoDB Extended JSON.
All your queries to MongoDB database that contains _id conditions should wrap _id in ObjectId function like the following:
db.resources.findOne({_id: ObjectId("507c35dd8fada716c89d0013")};
MongoLab provides UI for querying to MongoDB via JSON syntax. But you can't use ObjectId in JSON due specification restrictions.
So, MongoLab uses Strict MongoDB Extended JSON for alias ObjectId() -> $oid.
{"_id": {"$oid":"507c35dd8fada716c89d0013"})
Same $oid you see in the output because MongoLab UI uses JSON also.
Mongoose automatically converts a string _id to MongoDB query so you don't need doing it manually. The following queries are equivalent:
Resource.findById("507c35dd8fada716c89d0013");
Resource.findById(new mongoose.Types.ObjectId("507c35dd8fada716c89d0013"));

Access mongoose non-schema values in Jade

I have a really weird problem in Jade where I cannot access the values that aren't defined in the Schema.
I'm using strict:false on my schema and saving values to it. My data looks like this:
{
"title" : "This is a title in the schema",
"notInSchema" : "This will never show up"
}
This works:
h1= post.title
This doesn't work:
h1= post.notInSchema
If I dump all my data into the template, I can see both pieces of data:
pre= JSON.stringify(options,null,'\t') //{"title" : "This is a title in the schema", "notInSchema" : "This will never show up"}
If I add notInSchema to my schema, it shows up. How can I do this without adding it?
Instead of passing the raw Mongoose document to Jade, pass its serialized version instead:
res.render('yourtemplate', {
post : post.toJSON() // .toJSON() is also called by JSON.stringify()
});
I believe Mongoose only creates accessors on a document for fields that are in the schema. Any other fields, even though they are stored in the database, don't get one so can't be accessed directly.
The documentation seems to suggest something similar:
NOTE: Any key/val set on the instance that does not exist in your
schema is always ignored, regardless of schema option.
EDIT: since you're dealing with result sets, you need to call toJSON on each document in it. The easiest way to do so is using map (hope I get the CF syntax right):
res.render "admin",
title : "Admin Dashboard"
results : results
users : results.users.map (user) ->
user.toJSON()
messages: req.flash() || {}
Although that would still leave results 'unprocessed'. Alternatively, you could leave the mapping to the separate steps in your async.series. For instance:
Company
.find()
.exec (err,companies)->
next(null,companies.map (company) ->
company.toJSON()
)
Or use toJSON in your template on any object that you need to access those "unschema'd" properties for.
I use:
model.find({Branch:branch},function (err, docs){
if (err) res.send(err)
res.render('index',
{tree: tree,
articulos: JSON.parse(JSON.stringify(docs))
})})
});

Resources