Understanding Mongoose Schema better - mongodb

I am relatively new to the MongoDb world, coming from a MS Sql / Entity framework environment.
I am excited about Mongo, because of:
MongoDb's ability to dynamically change the shape of the class/table/collection at run time.
Entity framework does not offer me that.
Why is that so important?
Because I would like to create a generic inventory app and have the product class/collection/table be dynamic for clients to add fields pertinent to their business that cannot be used by everyone, eg. Vin Number, ISBN number, etc.
Now I have come to learn about Mongoose and how it offers a schema, which to me detracts from the flexibility of MongoDb described above.
I have read in a few sections that there is such an animal as mixed-schema, but that appears to be dynamic relative to the data type and not the collection of properties for the given class/collection/table.
So this is my question:
If I am looking at developing a generic class/collection /table that affords clients to shape it to include whatever fields/properties they want that pertain to their business, dynamically, should I abandon the whole notion of mongoose?

I found a benefit today as to where a Schema may be warranted:
Allow me to preface though and say I still thoroughly am excited about the whole idea that Mongo allows a collection to be reshaped at run time in circumstances where I may need ti to be. As mentioned above, a perfect example would be an Inventory app where I would want each client to add respective fields that pertain to their business as opposed to other clients, such as a Car dealership needing a VIN Number field, or a Book store needing a ISBN Number field.
Mongo will allow me to create one generic table and let the client shape it according to his own wishes for his own database at run time - SWEET!
But I discovered today where a schema would be appropo:
If in another table that will not be 're-shapeable', say a user table, I can create a Schema for pre-determined fields and make them required, as such:
var dbUserSchema = mongoose.Schema({
title: {type:String, required:'{PATH} is required!'},
FullName: {
FirstName: {type: String, required: '{PATH} is required!'},
LastName: {type: String, required: '{PATH} is required!'}
}
});
By having the respective first-name and last-name required from the schema, the database will not add any records for a user if they are not both included in the insert.
So, I guess one gets the best of both worlds: Tables that can be re-shaped and thru a schema, tables that can be rigid.

Related

Want to change a model ObjectID value

I am creating a Student and Course relationship
A student may have multiple courses. A one to many relationship.
This is made in Express and I'm using MongoDB. I have shorten the models to keep it simple
Student Model
const studentSchema = new mongoose.Schema({
name: {type: String},
courses: [{
type: ObjectId,
ref: 'class'
}]})
Course Model
const classSchema = new mongoose.Schema({
ClassId: {type: String,},
Grade: {type: Number,}, })
Currently, what I have is when I update the grade, it will update the grade values for the course itself and not the course in the user courses.
router.put(....)
const{username, courseId, grade} = req.params
const existingUser = await Student.findOne({username}).populate({
path: 'courses',
select:['ClassId','Grade']
})
const findCourse = existingUser.courses.find(
x => x.ClassId == courseId
)
findCourse.Grade = parseInt(grade)
await findCourse.save()
The problem is this will change the grade for the course itself. Meaning any student that adds this course will have that grade too.
I'll explain what I want to do in Java/OOP terms if that helps.
I want the student object to have it's own course objects. At the moment, it seems like classes are static class objects.
I want to access that specific student courses and change that student grade of that specific course.
Please help, I already spent a couple of hours on this. In SQL, the student would have a reference key and be able to easily change their values, I'm having trouble in MongoDB.
Alright, I finally figured it out. In hindsight, it makes sense. Gave myself a break from coding and came back to see the problem.
Lets pretend we have two students and one course. This courses is seeded with data.
When a student A picks that course, they add it to their course array. When student B wants that course, they also get that exact course. Now they are sharing the course. Basically, they are sharing the same reference.
The solution to this is to still find the course. Now make a new course object, copy every value of the original to the copy. Save the copy to the database and now you add that course to the student. Now we can still register for courses and use the seeded data and students don't share anymore.

Unsure how to model many-to-many relationship in MongoDB

I'm new to MongoDB and I'm trying to model a Many to Many relationship into at least 2 collections (I need two collections for the project). What I'm having is a collection of universities, faculties and specializations, and another collection for students and their gradebook (this was the middle entity between specializations and students in SQL, not sure if it's needed in Mongo anymore). I tried to use This as an inspiration but it limits me as I can only search students by university id (I want for example to search students from a certain specialization or a certain faculty). I could put every row from university, faculty and specialization in the student collection and vice versa but I really don't think it's ideal. Here's what I have so far:
db.students.insertOne({_id:1, firstname: 'John', lastname: 'Silas', ethnicity:'english', civilstatus:'single', residence:'London', email:'johnSilas#gmail.com', gradebook:[{ year:2018, registrationyear:2017, formofeducation:'traditional'}], universities:[1]})
db.universities.insertOne({_id:1, name:'University of London', city:'London', adress:'whatever', phone: 'whatever', email: 'whatever#gmail.com', faculty:[{name: 'Law', adress:'whatever', phone: 'whatever', email: 'whatever#gmail.com'}], specialization:[{name:'criminal rights', yearlytax:5000, duration: 3, level:'bachelordegree', language:'english'}], students: [1,2]})
I'm sorry if I don't understand basic noSQL concepts, I am new to it. Thanks in advance.
Basic patterns for many to many association between A and B:
Inline references
On A, store the list of B ids in a field like b_ids
On B, store the list of A ids in a field like a_ids
This requires two writes whenever an association is created or destroyed, but requires either zero or one joins at query time to traverse the association (if you just want the id of Bs for a given A and you have the A already no further queries are needed).
Join model
Create a model C which has two fields: a_id and b_id. Each association is represented by a single instance of C.
This requires one write whenever an association is created or destroyed, but requires joins on all queries involving association (potentially two joins per query).

Complex and multiple connected database relations in MongoDB

I am currently trying to model a MongoDB database structure where the entities are very complex in relation to each other.
In my current collections, MongoDB queries are difficult or impossible to put into a single aggregation. Incidentally, I'm not a database specialist and have been working with MongoDB for only about half a year.
To keep it as simple as possible but necessary, this is my challenge:
I have newspaper articles that contain simple keywords, works (oevres, books, movies), persons and linked combinations of works and persons. In addition, the same people appear under different names in different articles.
Later, on the person view I want to show the following:
the links of the person with name and work and the respective articles
the articles in which the person appears without a work (by name)
the other keywords that are still in the article
In my structure I want to avoid that entities such as people occur multiple times. So these are my current collections:
Article
id
title
keywordRelations
KeywordRelation
id
type (single or combination)
simpleKeywordId (optional)
personNameConnectionIds (optional)
workIds (optional)
SimpleKeyword
id
value
PersonNameConnection
id
personId
nameInArticleId
Person
id
firstname
lastname
NameInArticle
id
name
type (e.g. abbreviation, synonyme)
Work
id
title
To meet the requirements, I would always have to create queries that range over 3 to 4 tables. Is that possible and useful with MongoDB?
Or is there an easier way and structure to achieve that?

Selected Updates in Nested AppSync Schema

I am trying to carry out selected upates of individual nested fields with a DynamoDB table which is connected to an AppSync interface. I am able to update individual top level fields but when it comes to nested fields I am unsure how to approach. I am a newbie to this so perhaps I am thinking about this wrong and I need to flatten the data through the schema so that the data is flat in the DynamoDb tables. I have struggled to find an example of how to tackle this kind of situation with fairly complex tables. I am using the Custom Types to bring some standardisation across the App and different resolvers/.
We have a AppSync Schema defined approximately like this
type Main_entries {
id: String!
title: String!
recordInfo: CustomType
}
Type CustomType {
fieldA: String
fieldB: String
fieldC: String
}
What I have are some main types but also some Custom Types used throughout the application. What I want to be able to do is to update fieldB whilst keeping the rest of the data intact.
I have used the UpdateItem approach here
With this I can say update title whilst keeping the rest of the record intact but if my Mutation instructs fieldB to be updated a SET is created to update the entire recordInfo type so fieldA and fieldC are omitted.
Does anyone know of any ideas or even better know where there may be some examples.
Many thanks in advance.

Can I use NoSQL instead of a Relational Database?

For a library, I need to keep track of users and books. Basically I need to be able to know:
the list of books currently borrowed by a user
the current borrower of a given book
The app is done with node.js and mongoDB (with moogoose). I have the following schema:
BookSchema = new Schema({
title : String,
author : String,
current_borrower_email: String,
});
mongoose.model('Book', BookSchema);
// Define User model
UserSchema = new Schema({
lastname : String,
firstname : String,
email : String,
books : [BookSchema] // Books the user is borrowing
});
mongoose.model('User', UserSchema);
I guess this would be simplier to set this up in a relational DB where I could easily use many to many relation ships with foreign keys but I wanted to give a try to MongoDB.
Do you think this solution could work ? Also, if I delete a Book object, it seems I will have to remove it manually from the array of the user who borrowed it, it that right ?
In general mongodb will be good replacement of relational database for above task.
So some basics:
1.Once some one take a book you just need to copy book into the nested collection of user and user to the Book.
2.Once user has updated his profile you need aslo update information about user within Book.
3.Once book data was changed you also need update info about book within user.
4.If you trying to delete some book and current borrower exists you should say that book was borrowed by 'User' and not delete it.
I just suggest to add into your schema instead of current_borrower_email entire User object -> current_borrower: UserSchema.
So with such denormalized schema you will able easy show(within one request to mongodb):
the list of books currently borrowed by a user.
the current borrower of a given book
It is an old question but it came first in google so...
It's not too complicated but it is too long to summarize.
Read this:
http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1