I am new to Express and trying to make an app that saves and retrieves user notes in MongoDB by their username. The way I am doing it is by creating an object with the user and saving the notes as an array.
Here is my code in expressJS.
router.post('/editnotes', async (req, res) => {
const data = req.body
const { username } = req.query;
const findUserNotes = await Note.findOne({ username: username })
if (findUserNotes) {
findUserNotes.notes.push(data)
findUserNotes.save()
res.status(201).send('ok here')
}
if (!findUserNotes) {
const note = new Note({
username: username,
notes: [data]
})
await note.save()
res.status(200).send('ok here')
}
})
Here how it looks in MongoDB Compass.
"username": "Dhruv70",
"notes": [
{
"topic": "hello",
"content": "world"
},
{
"topic": "bye",
"content": "universe"
},
{
"topic": "xxxxxxx",
"content": "xx"
}
],
"__v": 31
}
It works, but I don’t think it’s a good solution, as adding, deleting, and editing everything in the array can be cumbersome. Is there a more efficient method for storing data?
I don't quite agree with the other answers so I decided to write up my own here
db.collection.update({
"username": "Dhruv70"
},
[
{
"$set": {
"notes": {
$concatArrays: [
{
$ifNull: [
"$notes",
[]
]
},
[
{
"topic": "new note",
"content": "to insert"
}
]
]
}
}
}
],
{
upsert: true
})
Mongo Playground with a match
Mongo Playground without a match
notes
level a lot, you might want to store notes as individual documents, instead of array entries.Generally speaking, NoSQL prefers denormalizing data over storing data in a traditional entity-relationship model. Some NoSQL databases do not even support join/lookup. You might want to check out this MongoDB official doc to learn more about MongoDB data modelling.
For your current use case, if you decide to refactor notes
as individual documents, you can have the below schema:
{
"topic": "hello",
"content": "world",
"username": "Dhruv70",
"__v": 31
// some other fields from original user level
},
{
"topic": "bye",
"content": "universe",
"username": "Dhruv70",
"__v": 31
// some other fields from original user level
},
{
"topic": "xxxxxxx",
"content": "xx",
"username": "Dhruv70",
"__v": 31
// some other fields from original user level
}
You can see that information for the user is duplicated across different notes. This is what denormalization means.
Pros:
username
field can be indexed for faster lookup and update of notesnotes
can be achieved with a single playing update.Cons:
user
level a lot, you might need to handle duplication/deduplication/potential inconsistency of user data.So in the end like all other design problems, there is no right/wrong answer to your data modelling problem. It is rather a trade-off between pros and cons of different options. The above is just my suggestion, based on my observation of the details you provided currently.