I have two models Users and News. On the page which is written with Express framework are published news and under the news are comments. Inside News model is subdocument with comments which contains two fields - user (subfields:) { name, objectid } and comment. Because in addition to comment there is user's name, I would like to add some additional informations about it (like number of comments, link to website, ...).
And this is my question: How to get data of user (from Users model) for each comment from subdocument (from News model)?
Add a populate call to your find query to pull in the user details. I'm not quite clear on your schema, but something like:
News.find().populate('comments.userId').exec(...);
This relies on your schema defining userId as an ObjectId ref to Users.
Related
When using a SQL database for creating a basic blog I would have an author table, categories table and the posts table. I would then use joins on the blog page to get the author name and category i.e.: in the posts table when creating a post the user ID and the category ID would be stored.
If the user loves dogs and they write 100 posts about dogs under the category, 'dogs' and one day the website owner decides to change that category name to 'canine', no big deal. Because of the database design, all 100 blog posts will show category name 'canine' now. Great!
I however want to set this up with Mongo and have read different views on this. Some say you should store the category _id in the posts table and use references, others say that is defeating the purpose of using a nosql database and you should just store the category name in the posts collection. Personally, I would love to do that but what happens when you have 10000000 blog posts with the same category name and then the category name in the category collection gets changed?
Does that mean that when the category name is changed, your code should also update every single blog post with that category, and how since all that is stored is the category name and not _id ?
So I have a very specific question about the optimum way of storing & then fetching data from a MongoDB database and ill try my best to explain the use case:
I have a content publishing platform that I've built. On this platform, a user can say, write a story, and the story gets saved as a document in the 'stories' collection in the database in a structure such as this:
{
_id : s_12345,
title : This is a story,
...
}
now on the same platform, let's say, another user writes a 'news article', which gets saved as a document in a separate 'news' collection. But now, the interesting thing is, while writing this news article, the user could 'tag' a story of their choice so that this news article would show up in a 'related content' section when some user on the platform is viewing that particular story. So the data structure of this news article could be:
{
_id : n_12345,
title : This is a news article,
related_to_tag : s_12345 //id of the story
...
}
Now from my understanding as of now, there are 2 ways of doing this:
OPTION 1: when a user tries to view this story (s_12345), we make a get request to the server, fetch this particular story document from the 'stories' collection in the database, then cycle through ALL the documents in the 'news' collection and pick up all the documents that have the related_to_tag === s_12345, and then return the story document + all these related news documents to the client. However this operation seems pretty expensive to me, especially if I have, let's say, 10,000 news articles in the news collection.
OPTION 2: At the time of posting the 'news article' to the database, I also find the story (s_123456) in the stories collection, and write a reference to the news article in this story document itself, like so:
{
_id : s_12345,
title : This is a story,
related_content : n_12345
...
}
The second option seems better to me. Because then, when a user tries to get the story, I already know all the other news articles that are related to it, and simply have to run a mongoose populate function to populate these news articles. but it brings up other complications such as:
what happens when the author of the news article deletes it? that means that I will have to find the story document (s_12345), and delete the related_content reference (n_12345) as well.
Or maybe I could run a weekly cron-job that does this sort of cleanup.
Also what happens if, while I am doing this double write operation (write the news article to database + write a reference to the news article to the story document), the second operation fails for whatever reason. that would create data inconsistency.
Anyway, this is a question that I have been struggling with for quite some time now, hope I have explained my use case clearly.
Awaiting your responses!
Abrar
I list the articles under the category. but there are more than one subcategory. I want to write these together in connection. I also want the page number in the form of /page/2. What kind of schema should I use here.
This is the current route. But isn't work
([a-z0-9-_/]+/)?:slug([0-9a-z-_]+)(/page/:page([0-9]+))?$
Link structure
category/[category]/[sub]/[sub-sub]/page/[number]
Sample Link
category/language/mobile/swift/page/2
And I want the last subcategory name. (swift)
Ok so I have a pretty simple DB setup in a MEAN app (node, mongoose, mongo) where I have Book records, and User records. A book has a single Owner, and can have any number of shared users which are stored in an array in a field called sharedWith:. Originally I was storing the user records with an email address as the _id field. I now realize this was a dumb move on my part because if someone wants to change their email address it effectively cuts them off from their books.
The app is not live yet, so it's not a fatal mistake.
My question is, once I revert the User documents to using the original hash value for _id, and store those in the Owner and sharedWith fields in the book documents, will I have to query each hash just to retrieve the actual usable user data?
I know mongoose has a .populate() method which will resolve sub documents, but as for inserting them? Will I POST the users as email addresses, then query each and store the resulting hashes? I can do this manually, but I wanted to make sure there is not some secret mongo-sauce that can do this in the DB itself.
Thanks!
If you have the _id available in the frontend for the user. You can directly share him a book by adding the _id to the sharedWith array of a book. But if you don't have the _id of the user available in the frontend, you need to manually get the _id by querying with the email and then store the _id in the sharedWith. As to retrieve the books, populate is indeed the best option to use to get user data.
And to get all books shared with a user you can do something like this,
Book.find({sharedWith:user1._id},function(err,docs){ });
This query can be made efficient if you use an index on sharedWith but that depends on your use case.
I really like the document-based approach of storing data like blog posts as a whole document with all information needed saved inside of it. Therefore the authorĀ“s username is stored as plain text. The author himself has his own document with personal information attached to it. What happens when the author decides to change his username? Do I have to update every document the contains a blog post by that author or is this just one of the drawbacks using a document-based database?
Thanks for any suggestions!
If you need to write a query(view) with content from the blogpost and the name of the author, then the name must be included in the blog content, and therefore all blogposts must be updated.
if the name is only for information ( i mean you do not query a blogpost-content like keywords AND name of author), you can add the id into the blog document (and of course now can Query blog content AND author-id) and emit {'_id':doc.author_id} as a Value.
include_docs=true then gives you the doc of the Author (and no longer the blogpost-doc.. you have to call it explicit with the id thats in the result rows). No Need to update the blogposts.
Example:
Case 1:
Use Author by Name, you have to include the name, and therefore update ALL docs.
{
"_id":"blogpost1",
"author":"Oliver",
"keyword":"couchDB"
}
to look for all couchdb posts from oliver:
emit ([doc.author,doc.keyword],1)
call:
&key=["Oliver","couchDB"]
Case 2:
No need to query by name
{
"_id":"blogpost1",
"author_id":"author-123",
"keyword":"couchDB"
}
emit (doc.keyword,{'_id':doc.author_id})
and the authors doc:
{
"_id":"author-123",
"name":"Oliver"
}
call:
?key=["couchDB"]&include_docs=true
result:
...
{"id":"blogpost1","key":"couchDB","value":{"_id":"author-123"},"doc":{"_id":"author-123","_rev":"xxx","name":"Oliver,....