I have a Company schema:
var CompanyEntityModel = new Schema({
name: String,
street: String,
zipCode: String,
city: String,
members: [Useraccount]
});
And a Useraccount schema:
var UseraccountEntityModel = new Schema({
firstName: String,
lastName: String,
email: String,
password: String,
companies: [Company],
});
In my scenario I save the useraccounts in a useraccount collection (inside the db) and as embedded document inside the company. So a company can have n useraccounts.
I do the same with companies (they are saved inside a company collection and as embedded document inside a useraccount. A useraccount can have n companies).
I could also just save the objectIds to members (in Company schema) and to companies (in Useraccount schema).
What is better? If I stick to my solution and the company gets updated ... do I have to update the document in my companies collection and also all the companies which are embedded documents inside the useraccounts?
that might help you: http://docs.mongodb.org/manual/reference/database-references/
My preferred way is saving the object id into the second collection and perform on application side an second query to get related data.
Related
I have a schema which shares multiple fields between my model. Here are a simple representation of the schemas.
const productSchema = new mongoose.Schema({
productName: String,
productId: String,
productAltCode: String,
description: String,
}
const cartSchema: new mongoose.Schema({
productId: String,
productAltCode: String,
...
}
Here I have 2 fields which are the same in both models, productId and productAltCode. Is there a way to not duplicate in both schemas? I have this type of scenario with other objects in my model and just think there may a way to not duplicate the fields
Suppose I have the following schema:
const personSchema = mongoose.Schema({
firstname: String,
lastname: String,
email: String,
gender: {type: String, enum: ["Male", "Female"]}
dob: Date,
city: String,
interests: [interestsSchema],
// vs this
// interests: [{type: Schema.Types.ObjectId(), ref: 'Interest'}]
});
What are the difference between the two methods here? What are the advantages and disadvantages of one vs the other?
There is obviously no perfect answer to this question, it all depends on the scenario, where and how will you use the data.
ObjectId vs Embedded
I use both embedded documents and lists of ObjectIds. For example, I have two collections, Customers and Contacts. Every Customer can have multiple contacts, and multiple Customers should be able to use the same contact.
We also want to list and manage contacts separately.
We also have an array of addresses, which is unique to each Customer document, we do not need to list or manage them separately or reuse them ever again, so it makes sense to embed them.
Customer
{
businessName: string,
contacts: [ObjectId, ObjectId],
address: {
invoice: [{
street: string
zip: string
city: string
}]
}
}
Contact
{
firstName: string
lastName: string
phoneNumber: string
email: string
}
Array size
This is just a side note, not relevant to the question, just some more information about arrays in MongoDB.
What you are describing here is a so called one-to-many relationship, where one document may have any number of embedded documents.
MongoDB works best with "one-to-few" when using any type of array, they usually recommend you to not have an array containing more than a hundred documents, if there are more, it will start to impact query times in one way or another.
The same goes for the ObjectId array, it should not be more than a hundred in the array.
If you expect the array to increase beyond a hundred, you should use a separate collection with a property like personId where every interest refers to the person. This way, you don't need the array at all in the personSchema.
I have a model Franchise that has another Schema Employee as its subdocuments for a field. The structure is as follows.
Franchise.js
const Franchise = new mongoose.Schema(
{
franchiseName: String,
address: String,
managers: [Employee]
});
export default mongoose.model(
"Franchise",
Franchise
);
Employee.js
const Employee = new mongoose.Schema(
{
name: String,
email: String,
phoneNo: Number,
password: String,
});
export default Employee;
The issue I am facing is with every query to Franchise, it returns a new _id for the objects in managers field. Is there any way to make it constant ?
For instance, I am running a simple findById on Franchise and store it in franchise variable.
and then I console.log(franchise.managers).
It prints different IDs each time the query is run.
[
{
_id: new ObjectId("61925d2697852574eb0ba9ab"),
name: 'Franchise Manager 1',
email: 'franchise1#sfc.com',
phoneNo: 1234567890,
}
]
Second time the query is run:
[
{
_id: new ObjectId("61925ba8130aca93a7dd3dbc"),
name: 'Franchise Manager 1',
email: 'franchise1#sfc.com',
phoneNo: 1234567890
}
]
As you can see, the employee is the same, however it has different Id for each call. Kindly help.
Thanks.
Alright, I figured it out. The issue is that there was no _id stored in the database for existing data of managers. The Employee schema was added later on, so as the _id was not present in the database only, a new one was being generated each time.
I am trying to implement a collection in meteor/mongo which is of following nature:
FIRST_NAME-------LAST_NAME-------------CLASSES----------PROFESSORS
----------A-----------------------B------------------------------a---------------------b
-------------------------------------------------------------------c---------------------d
-------------------------------------------------------------------e---------------------f
-------------------------------------------------------------------g---------------------h
-------------M-------------------------N------------------------c---------------------d
-------------------------------------------------------------------p---------------------q
-------------------------------------------------------------------x---------------------q
-------------------------------------------------------------------m---------------------n
-------------------------------------------------------------------r---------------------d
So as above, a person can take multiple classes and a class can have multiple people. Now, I want to make this collection searchable and sortable by all possible fields. (Also that one professor can teach multiple classes.)
Searching by FIRST_NAME and LAST_NAME is easy in above shown model. But, I should be able to see all student depending on the class I select. I would also want to see list of classes sorted in alphabetical order and also the people enrolled in corresponding classes?
Can you please let me know how to approach this in a meteor/mongo style? I would also be glad if you could lead me to any resources available on this?
You are describing one of the typical data structures which are better suited for a relational database. But don't worry. For reasonably sized data sets it is quite workable in MongoDB too.
When modelling this type of structure in a document database you use embedding, which does lead to data duplication, but this data duplication is typically not a problem.
Pseudo-code for your model:
Collection schoolClass: { // Avoid the reserved word "class"
_id: string,
name: string,
students: [ { _id: string, firstName: string, lastName: string } ],
professor: { _id: string, firstName: string, lastName: string }
}
Collection student: {
_id: string,
firstName: string,
lastName: string,
classes: [ { _id: string, name: string } ]
}
Collection professor: {
_id: string,
firstName: string,
lastName: string,
classes: [ { _id: string, name: string } ]
}
This gives you easily searchable/sortable entry points to all objects. You only follow the "relation" _id to the next collection if you need some special data from an object. All data needed for all documents in the common queries should be present in the Collection the query is run on.
You just need to make sure you update all the relevant collections when an object changes.
A good read is https://docs.mongodb.com/manual/core/data-modeling-introduction/
I am creating passport authentication for node using mongoose. I don't have any collection called "users" in my database. But while creating new user using the schema like below
var mongoose = require('mongoose');
module.exports = mongoose.model('User',{
id: String,
username: String,
password: String,
email: String,
firstName: String,
lastName: String
});
It will automatically creates new "users" collection.
How is this possible?
Here mongoose will check if there is a collection called "Users" exists in MongoDB if it does not exist then it creates it. The reason being, mongoose appends 's' to the model name specified. In this case 'User' and ends up creating a new collection called 'Users'. If you had specified the model name as 'Person', then it will end up creating a collection called 'Persons' if a collection with the same name does not exist.
Mongoose pluralizes the model name and uses that as the collection name by defualt. If you don't want the default behavior, you can supply your own name:
const UserModel = mongoose.model('User', new Schema({ ... }, { collection: 'User' }));
Ref: https://mongoosejs.com/docs/guide.html#collection