I am developing a blog website (to practice for ReactJS).
In my website, I have a slide bar will show categories and number of posts in each category.
So, how should i design category collection?
Having a field named numPosts to store total posts in that category.
And whenever i create new post document, i must increase numPost
field in it.
Don't store total posts in category collection. Everytime i want to
fetch number of posts, i have to browser post collection and count.
Is there any best design for this case?
Thank you in advance for your help!
Sorry about my English.
This is better to count the posts (via count or $count) instead of create "numPosts" field,
don't act like relational databases , following schema is a good one for what you want to do:
{
"_id" : ObjectId("5e60df95d7ff5f38b4d44d8c"),
"nameOfCategory": "Coronavirus",
"postsInsideThisCategory: [{
"titleOfPost": "Is there any cure?",
"description": "Bla Bla Bla Bla..... and Bla"
},{
"titleOfPost": "What is the type of coronavirus?",
"description": "Bla Bla Bla Bla..... and Bla"
}]
}
Then just use count or $count to count the number of documents inside the array of "postsInsideThisCategory" field.
Related
I have a current structure in my firestore.
Data model:
- users (collection)
- 9d5UCo4RtyTosiFAIvnPK4zFCUk1 ( each user is a separate document )
- trips ( collection )
- New York (Document)
- fields: date, description, photos:[url1, url2, ....] ( fields in the New York document), status:public
- Los Angeles
....
Now I want to add notes, likes and metadata for each photo in the New York, LA, etc photos array.
I have a few ideas but not sure which is scalable and works well for what I want to do with notes, likes and metadata.
The notes don't have to load at the same time the photos do. The user would click to open notes which could be a new query to DB. But each photo does need to know how many notes are associated with each photo when photos are been displayed.
Solution 1:
photos array would be an object instead.
const photos = {
isdffd: {
url: "path",
likes: 100,
metadata: {
...
},
},
xxydfsd: {
url: `path`,
likes: 10,
metadata: {
...
}
},
};
Then I have a collection of notes back up where trips is and use the photo id as the id for the note. but that limits me to 1 note per photo which I want to be able to add multiple notes.
I also want to be able to build a search page which would search through all notes throughout all trips and display them grouped by trip in the results.
What would be a good approach for this kind of setup with what I have right now which is using sub-collections for most of my structure so far.
Solution 2:
add another sub-collection inside each trip document called photos
each photo would be its own document with likes, metadata and notes. But then notes needs to be a sub-collection of each photo document. This would make it hard to search all trips and all notes for each photo.
The way your original function has been structured:
- users (collection)
- 9d5UCo4RtyTosiFAIvnPK4zFCUk1 ( each user is a separate document )
- trips ( collection )
- New York (Document)
- fields: date, description, photos:[url1, url2, ....] ( fields in the New York document), status:public
- Los Angeles
....
If you implement the first solution, you will limit your code if in the future you want to add another field to the photos object, or as you add additional photos to the object.
Adding a photos sub-collection inside your trips is your best option, this way your collection can grow and avoid the limitation of the first solution (having to make any change manually). If your notes are only text, then you can keep them inside each photo document as an array, avoiding another subcollection. Keeping the photos as a sub-collection and keeping the URL, likes, metadata and notes (if they are only text) inside each photo created should not add much difficulty when querying.
Below is my MongoDb collection structure:
{
"_id": {
"$oid": "61efa44933eabb748152a250"
},
"title": "my first blog",
"body": "Hello everyone,wazuzzzzzzzzzzzzzzzzzup",
"comments": [{
"comment": "fabulous work bruhv",
}]
}
}
Is there a way to auto generate ids for comments without using something like this:
db.messages.insert({messages:[{_id:ObjectId(), message:"Message 1."}]});
I found the above method from the SO question:
mongoDB : Creating An ObjectId For Each New Child Added To The Array Field
But someone in the comments pointed out that:
"I have been looking at how to generate a JSON insert using ObjectID() and in my travels have found that this solution is not very good for indexing. The proposed solution has _id values that are strings rather than real object IDs - i.e. "56a970405ba22d16a8d9c30e" is different from ObjectId("56a970405ba22d16a8d9c30e") and indexing will be slower using the string. The ObjectId is actually represented internally as 16 bytes."
So is there a better way to do this?
My goal is to find songs that match user's choices. User has the opportunity to exclude genres he doesn't like.
This is basically a duplicate of this question, except that I'd like to be able to do this in an Aggregate operation instead of a Find, as I need to add other stages.
Right now, I am trying in an aggregation to exclude songs that belong to genres user doesn't like.
My song json is as such (keep in mind this is dummy data - but this song is really good though):
{
"_id": {
"$oid": "5890aa3b0a9f110011698fac"
},
"artist": "Beach House",
"songName": "Master Of None",
"genres": [
{
"$oid": "58624b4298fba881a46663a01"
},
{
"$oid": "58624b9d98fba772a46663a05"
}
]
}
A song can have multiple genres, stored in an array of objects as references to Genre documents in a different collection.
Basically, user's disliked genres are in an array of genre $oid.
Say
dislikedGenres = [ "786761gg1G176ga1", "78676187g1G176hsj3", "78676187g1G1761sj4" ]
What I'm trying to do is say "if you find a song with any of these genres, exclude it".
Any idea how to achieve this? I feel like I'm missing something dramatically obvious here...
Thanks in advance for the help! Much appreciated.
Please leave a comment if you need extra info.
Let's say I have the following document schema in a collection called 'users':
{
name: 'John',
items: [ {}, {}, {}, ... ]
}
The 'items' array contains objects in the following format:
{
item_id: "1234",
name: "some item"
}
Each user can have multiple items embedded in the 'items' array.
Now, I want to be able to fetch an item by an item_id for a given user.
For example, I want to get the item with id "1234" that belong to the user with name "John".
Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.
I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.
Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.
Thanks for any help or advice you can provide.
The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })
You will have :
{
name: "John",
items:
[
{
item_id: "1234",
name: "some item"
}
]
}
See Documentation of $elemMatch
There are a couple of things to note about this:
1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.
2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.
In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.
3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.
4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.
If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).
If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.
A sample document might look like this:
{
_id: {user_id: ObjectId, item_id: "1234"},
name: "some item"
}
Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).
I'm new bee in mongodb.
I made a nested array document like this.
data = {
"title": "mongo community",
"description": "I am a new bee",
"topics": [{
"title": "how to find object in array",
"comments": [{
"description": "desc1"
}]
},
{
"title": "the case to use ensureIndex",
"comments": [{
"description": "before query"
},
{
"description": "If you want"
}
]
}
]
}
after that, put it in the "community"
db.community.insert(data)
so,I would like to accumulate "comments" which topics title is "how to find object in array"
then I tried,
data = db.community.find_one({"title":"mongo community","topics.title":"how to find object in array" } )
the result is
>>> print data
{
u 'topics': [{
u 'comments': [{
u 'description': u 'desc1'
}],
u 'title': u 'how to find object in array'
},
{
u 'comments': [{
u 'description': u 'before query'
},
{
u 'description': u 'If you want'
}],
u 'title': u 'the case to use ensureIndex'
}],
u '_id': ObjectId('4e6ce188d4baa71250000002'),
u 'description': u 'I am a new bee',
u 'title': u 'mongo community'
}
I don't need the topics "the case to use ensureIndex"
Whould you give me any advice.
thx.
It looks like you're embedding topics as an array all in a single document. You should try to avoid returning partial documents frequently from MongoDB. You can do it with the "fields" argument of the find method, but it isn't very easy to work with if you're doing it frequently.
So to solve this you could try to make each topic a separate document. I think that would be easier for you too. If you want to save information about the "community" for forum, put it in a separate collection. For example, you could use the following in the monbodb shell:
// ad a forum:
var forum = {
title:"mongo community",
description:"I am a new bee"
};
db.forums.save(forum);
// add first topic:
var topic = {
title: "how to find object in array",
comments: [ {description:"desc1"} ],
forum:"mongo community"
};
db.topics.save(topic);
// add second topic:
var topic = {
title: "the case to use ensureIndex",
comments: [
{description:"before query"},
{description:"If you want"}
],
forum:"mongo community"
};
db.topics.save(topic);
print("All topics:");
printjson(db.topics.find().toArray());
print("just the 'how to find object in array' topic:")
printjson(db.topics.find({title:"how to find object in array"}).toArray());
Also, see the document Trees In MongoDB about schema design in MongoDB. It happens to be using a similar schema to what you are working with and expands on it for more advanced use cases.
MongoDB operates on documents, that is, the top level documents (the things you save, update, insert, find, and find_one on). Mongo's query language lets you search within embedded objects, but will always return, update, or manipulate one (or more) of these top-level documents.
MongoDB is often called "schema-less," but something more like "(has) flexible schemas" or "(has) per-document schemas" would be a more accurate description. This is a case where your schema design -- having topics embedded directly within a community -- is not working for this particular query. However there are probably other queries that this schema supports more efficiently, like listing the topics within a community in a single query. You might want to consider the queries you want to make and re-design your schema accordingly.
A few notes on MongoDB limitations:
top-level documents are always returned (optionally with only a subset of fields, as #scott noted -- see the mongodb docs on this topic)
each document is limited to 16 megabytes of data (as of version 1.8+), so this schema will not work well if the communities have a long list of topics
For help with schema design, see the mongodb docs on schema design, Kyle Banker's video "Schema Design Basics", and Eliot Horowitz's video "Schema Design at Scale" for an introduction, tips, and considerations.