I am wondering which is better in terms of performance.
Let's say i have this Menu Schema
{
restaurant: { type: String, unique: true, required: true },
color: { type: String, required: true },
}
And i have this Plate Schema
{
name: { type: String, unique: true, required: true },
}
If i want to get all the plates from the Menu, which option is better?
Associate the Menu with plates like this:
{
restaurant: { type: String, unique: true, required: true },
color: { type: String, required: true },
plates: [
type: Schema.Types.ObjectId,
ref: 'plate'
]
}
Or like this:
{
name: { type: String, unique: true, required: true },
menu: {
type: Schema.Types.ObjectId,
ref: 'plate'
}
}
With the first option, i would use Menu.findById(id).populate('plates') to get the menu and all the plates associted with it. But with the second option, i would use Plate.find({menu: menu_id})
So, which is faster considering that i could have any amount of plates?
And if they are the same, is there a better way of associate Plate and Menu and get plates from Menu?
In terms of the performance, the second one would be faster because the first one would do the $lookup behind the scene (when doing populate), which is actually additional database call.
I would suggest the third option, which would be the best in your use case. That is embedding the plate documents inside the menu document.
{
restaurant: { type: String, unique: true, required: true },
color: { type: String, required: true },
plates: [
{
name: { type: String }
}
]
}
This way, menu document will contain all the information you needed and you can fetch everything with one database call.
Note: There is a limitation of 16MB for each document in the MongoDB. You can for sure store thousands or tens of thousands plates in each menu without a problem. But if you need to store much more in each menu, then you should go with some of your initial setups.
Related
I want to do a big project API where people can login with Google, send the token and when logged in do some actions saved to Mongo DB.
The problem is the tables structure, or schema. So, I want to do a good app scalable.
I have some tables like Users (with users loggin information) and I want user save his tasks, memories, works and more for him self, and when logged in in another device, get this information and modify.
Do I need to do every table for every user or use same table filtered by user?
For example, I have now this model for product:
const ProductoSchema = Schema({
nameOfProduct: {
type: String,
require: [ true, 'Required name' ],
unique: true
},
state: {
type: Boolean,
default: true,
required: true
},
userOwner: {
type: Schema.Types.ObjectId,
ref: 'Usuario',
required: true
},
priece: {
type: Number,
default: 0
},
category: {
type: Schema.Types.ObjectId,
ref: 'Category',
required: true
},
description: {
type: String
},
disponibility: {
type: Boolean,
default: true
},
img: {
type: String
},
});
Is this correct or this is not scalabe and I need to do all tables for every user?
I want to find out how I can display the username of a user. For example user admin posts a forum, then I would see Created By: admin on the forum page, instead I can only fish out the ID.
I don't know a much about mongoose and I need someone who is familiar with it.
My Forum Model:
You see I have only ref: 'user' and this is grabbing the ObjectId("") from the User.
const forumSchema = ({
forumName: {
type: String,
required: true,
},
forumDescription: {
type: String,
required: true,
},
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
published_on: {
type: String,
default: moment().format("LLL")
},
});
my userModel:
const UserSchema = mongoose.Schema({
userID: {
type: String,
required: true,
},
userName: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
isAdministrator: {
type: Boolean,
deafult: false,
},
});
Front-end :
As you can see only in {forum.user} there I can see the id from the user but I want his name not the id
<footer className="blockquote-footer">
Created by:{forum.user}
Created on:{forum.published_on.substring(0,300)}
</footer>
Since you are using 'ref' to reference the user table. When you are fetching a forum document, use the populate() function in mongoose to get all the user details as a sub-object to the forum document.
example: forumShcema.find({_id:<forum_id>}).populate('user').exec()
I'm currently struggling with a project of mine.
I've got a collection called "Games" and one "Participation".
When a user loggs in, he/she should be able to see the games and the individual participation status.
Therefore, I want to join these two collections but I can't use .populate() because I can't enter the neccessary Participation ID in the Games collection due to the fact, that I don't have the participation ID at the time I create a game. (So I would need to save the participation, remember the created ID and insert THIS id in the games collection afterwards)
The other way round would be a good solution (to populate Games in Participation) but initially, there are no participations in these collection, until a user clicks "Participate" or "Not Participate".
Basically I need a SQL query like that:
select * from games g, participation p where g.gamesId = p.gamesId AND p.username = [...]
Is there any possibility to achieve this?
Otherwise I would need to save every participation as a "Game", having the dependent username and his/her participation status in it.
Wouldn't prefer this solution at all.
Thanks in advance!
In case it helps:
Here are my two collections:
Game:
var gameSchema = mongoose.Schema(
{
isHome: { type: Boolean, required: true },
time: { type: String, required: true, max: 100 },
uzeit: { type: String, required: true, max: 100 },
clubId: { type: mongoose.Types.ObjectId, required: true },
enemy: { type: String, required: true, max: 100 },
place: { type: String, required: true, max: 100 },
(participation: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Teilnahme' }])
});
Participation:
var participationSchema = mongoose.Schema(
{
playerAvailable: { type: Boolean, required: true },
clubId: { type: mongoose.Types.ObjectId, required: true },
gameId: { type: mongoose.Types.ObjectId, required: true, ref: 'Game' },
memberName: { type: String, required: true },
}
);
How can I store userid's of meteor account-users in a collection2 array. My definition of schema looks like. Will this work?
I wanted an approach to add associated users to a collection. Whereby I wanted to control who are allowed to see this particular document of the collection. Is there a better way to do this than how I'm modelling.
name: {
type: String,
max: 100,
optional: false
},
billingAddress: {
type: AddressSchema
},
shippingAddress: {
type: [AddressSchema]
},
type: {
type: String,
max: 20,
allowedValues: ['Vendor', 'Customer', 'Self', 'Employee'],
optional: false
},
phones: {
type: [String]
},
emails: {
type: [String],
regEx: SimpleSchema.RegEx.Email
},
website: {
type: String,
regEx: SimpleSchema.RegEx.url
},
isCustomer: {
type: Boolean,
optional: false
},
isVendor: {
type: Boolean,
optional: false
},
isSearchable: {
type: Boolean,
optional: false
},
associatedUsers: {
type: [Meteor.users]
}
Each document receives an _id automatically. It isn't recommended to put _id in the schema. Not sure it will even work for you.
If you want to know if it will work, I recommend trying it yourself! You have the schema already.
For user permissions, I recommend using the alanning:roles package. That should solve your issues.
I'm doing a MMO Real-Time Browser game, and I'm storing data using Mongoose (MongoDB).
First of all, I'll show you the structure of my object:
var playerSchema = new Schema({
name: { type: String, required: true, trim: true, index: { unique: true } },
resources: {
wood: { type: Number, required: true, default: 500},
stone: { type: Number, required: true, default: 300},
iron: { type: Number, required: true, default: 0},
cereal: { type: Number, required: true, default: 0}
},
resourcesPerHour: {
woodPerHour: { type: Number, required: true, default: 40},
stonePerHour: { type: Number, required: true, default: 20},
ironPerHour: { type: Number, required: true, default: 0},
},
res: {type: Array, required:true, default: []},
buildings: { type: Array, required: true, default: []},
researches: { type: Array, required: true, default: []}
});
As you can see, res, buildings, and researches are arrays. I'm gonna show you one of them (they all have the same structure):
var buildingSchema = new Schema({
id: {type: String, requried: true},
name: { type: String, required: true, trim: true, index: { unique: true } },
level: { type: Number, required: true, default: 0},
scalingValue: {type: Number, required: true, default: 2},
costs: {
wood: { type: Number, required: true, default:0},
stone: { type:Number, required:true, default:0},
iron: {type:Number, required:true, default:0},
cereal: {type:Number, required:true, default:0}
}
});
OK, imagine I have a player, with all data initializated. When I try to update something, I can only update information out of that lists. Look this example:
player.findOne({name:req.session.name}, function(err, doc){
doc.resources.wood -= 200;
doc.buildings[id%100].costs.wood *= 2;
doc.save(function(err){
if(err)console.log(err);
});
}
When I look the model on database, it only stored the resources.wood, not the building[i].costs.wood. I don't know why it's failing, but all objects inside the arrays are created using a new variable, where variable is a Schema (like buildingSchema).
One more thing, I added a console.log(doc.buildings[i].costs.wood); just before the doc.save() and it's ok. So it means all the data is modified fine, but in the doc.saveit only save the 'not-in-list' data.
EDIT: console.log(err); doesn't print nothing, so it means the save function worked.
When you use the Array type in your schema (same as the Mixed type in the docs), you need to explicitly mark the field as modified or Mongoose won't save any changes you make to it.
doc.markModified('buildings');
doc.save(function(err){
if(err)console.log(err);
});
The better approach may be to declare buildings as containing an array of buildingSchema:
buildings: [buildingSchema],
That way Mongoose will be able to track the changes you make to the buildings array automatically.
https://groups.google.com/forum/#!topic/mongoose-orm/5m7ZPkhFyrc
Subdocuments that are not inside of an array are not supported by mongoose. My recommendation is to drop mongoose completely and just use direct queries to the db. You'll find the node native driver is quite easy to use.