This question already has answers here:
Why does Mongoose have both schemas and models?
(6 answers)
Closed 8 years ago.
i'm suprised this question hasn't been asked before, makes me kinda worry actually about my ability to understand how things work on my own....
In object oriented programming, we firstly define the abstraction, the class, and then we instantiate many concrete objects, based on the abstraction.
Why do we need to define both a Schema and a Model with Mongoose ? Aren't these 2 steps the same thing ?
The simple reason is that "model" and "schema" are two totally different things.
A "schema" defines the type constraints and other logic than can refer to how you want to "define" an object. Thee are many methods to do this including basic type rules right through to defining certain methods for validation or even dynamic field construction. A Schema is basically a extended definition of an object.
A "model" is something that actually "ties" to storage. In that it means there is something defined in "where" to actually store the the information. The "methods" used to interact with storage are also generally associated with a model. So you can save, or find or delete based on the model association. A "schema" can therefore be "tied" to various "models", as a model is all about a storage location.
So in the basic mongoose sense, a "schema" is not something that is necessarily tied in a "one to one" relationship to a "model". A schema can have many models and therefore the separation is made.
Related
I have a UML class Student that has an attribute id. I want to write a query in OCL to find a particular Student by only knowing its id. Should I use allInstances()? Or derive? I'm not very familiar with OCL.
Usually OCL is used to express some constraints on an UML model, in relation to a given class instance (context or self) and you’ll start navigating from a specific instance.
But OCL was developed as a formal specification language that can be used to specify more than only constraints, and in particular queries as explained in section 7.1. of the OCL specifications.
If you want to express something regarding all the possible instances of a class MyClass, you would then start your clause with:
MyClass.allInstances()
Wich is a set containing all the instances of the given class. Typically, you would then operate on this set to further specify some model features.
For example, to express uniqueness of an id, you would write a Boolean clause on this set (based on example of section 7.5.10 of the OCL specs)
MyClass.allInstances()->forAll(e1, e2 | e1 <> e2 implies e1.id <> e2.id)
One of the operation you can perform on such set is to create a subset by selecting elements that match a certain condition, and this should answer your question:
MyClass.allInstances()->select(c|c.id='...')
Additional thoughts:
OCL is an abstract language. Nothing is said on how this expression will be implemented. It could be a large inefficient iteration over an in-memory collection, or a very effective SQL query. OCL will help you to define what the result should be, but not how to really get it. So performance should not be your concern at this level of abstraction.
Now, you didn’t tell the purpose of your OCL query. If it is to explain how database queries will be performed, you could see some advantages in separation of concerns: identify the relevant classes and reusable queries and enrich your model using the repository pattern: a repository is a (singleton) class MyClassRepository that acts as a container of all objects of a given MyClass in the database. You would then define operation for manipulating and querying the database. Typically, you’ll have a couple of getXxxx() operation like getById() that return one or a set of several instances. First it will make explicit what is to be implemented as a database functionality, second the new operations can be used to simplify some OCL expressions.
Yes. allInstances() is the easy solution, but potentially the least efficient and not necessarily flexible.
If your application and constraints (for one School) are expanded to multiple schools you may realize that actually you wanted the Student at a particular School, so it is often better to go to the logical context and invoke a method on the School to return a given Student. Perhaps this is what you meant by 'derive'. The implementation of School.students->at(id) might well use a Map giving multiple gains, through not searching the whole model for every access and through having a fast access to what you have already got.
I've never made a class diagram before, that's why I tried to ask. I always learn from my mistake. I have read some references, but I am confused how to test the results I made? because this is not a coding which if have error, the error message will be appear.
this my design database
and this is a class diagram that I made based on design database.
is the method for creating class diagrams similar to erd? I am very confused how to inherit the class and which arrow should I use?
in the path that I made there are three users. and each has a different role
Public Relations = Input data from external user (the applicant comes and gives a written proposal) then the data is stored in the database. The data includes applicant data and proposal data. PR can also see data that has been confirmed by the Division
Division = The division can see data that has been stored by PR and confirm the data. Data that has been confirmed will be filed and made a report.
Manager = can only see reports
Here are a couple of findings:
User->Login: This is no generalization. A user isn't a login. It might have some login information associated. So that shall be an association.
Similar for Proposal->StatusProposal. But here it's a dependency since you will not create an enumeration object. You just use it to type an attribute.
Same for User->Gender/RoleUser. Both are dependencies.
There are also a couple of design issues. But here YMMV too much. Having User implement userLogin() is at least questionable. There should be a security system taking care which validates a user login. So why does Login have a loginStatus()? However, design is not be discussed here.
As to class/ERD: they are similar, but not the same. UML has a broader scope while ERD focuses plainly on databases. So all the *_id attributes in your classes stem from a database design. The class design in that state is very much focused on databases. In a MDA it might be derived from a PIM to a PSM (so from an abstract view to a DB-specific one).
In addition to Thomas Killian's observations, your composition associations appear to be inaccurate. In effect, for example, you are specifying that the lifetime of a Department object is dependent on the lifetime of a User object. You are also specifying a whole-part relationship between Users and Departments, where the user is an aggregation of departments. I would think that it's the other way around. I also suspect that a user's lifetime isn't dependent on a department's lifetime, since a user can typically change departments. Therefore, an aggregation diamond (white) is probably correct, and it should be on the Department end.
Similarly, I have trouble making sense of your other two composition associations.
This question already has answers here:
UML aggregation vs association
(8 answers)
Closed 4 years ago.
is there any why to know which one of two types of interaction
mentioned[aggregation or association] should be used in class diagram
?
is it even matter to specify which one to use in a certain interaction ?
Assosiation
The most abstract way to describe static relationship between classes is using the Association link, which simply states that there is some kind of a link or a dependency between two classes or more.
Aggregation
In cases where there’s a part-of relationship between ClassA (whole) and ClassB (part), we can be more specific and use the aggregation link instead of the association link, highlighting that the same ClassB instance can also be aggregated by other classes in the application (therefore aggregation is also known as shared association).
If you want to read detailed description then check this LINK
In many case, I need write a lot of class work with CRUD for some class. For example CRUD with pure object User, Book, Tag.
I usually make a directory named models, put all the CRUD classed into the models folder.
But I feel that the word model is not show essence. Is the word model well-defined in computer science? It means the pure object of User, or the means of CRUD of User?
I also use another name services for more complex logic, For example UserService may require other models than UserModel. But the word service is often conflict with some other case like an online service, backend service.
Are there any good names for the model and service in my case? BTW, I am most using Node.js; it may not conflict with the general conventions used in Node.js.
Ultimately, it will come down to what makes the code the most understandable both to you and to someone down the road who may have occasion to work on your code. If 'model' and 'services' convey the thought of what lies within in an obvious way to anyone coming in to the code, then they are probably fine. As far as standards, I don't know if there is a 'defined' set of names you have to use. In MVC, for example, you will use 'Models' as one of your folders in order to store all of the actual models you will be feeding your views, and this is understood in the MVC architecture that those names (Models, Views, Controllers) are the standard.
I agree with you that Model is a little ambiguous. Sometimes it is used to indicate domain objects such as User/Book/Tag, but sometimes it is used to indicate objects that deal with business logic, such as "Buying a book","Authenticating a user".
What's common to both uses is that "Model" is clearly separated from UI, that is handled entirely by the Views and the Controllers.
Another useful name is Entities. In Robert Martin's work on Object Oriented Design, he speaks of use-case-driven design, and distinguishes between three kinds of objects: Entity Objects, Interactor objects and Boundary objects.
Entity objects are useful in multiple use-cases. For example, in a book selling system, entities can be Book/User/Recommendation/Review.
Interactor objects implement use-cases, and they typically use multiple entity objects. For example, Purchase_Book/Login/Search_Books can be such objects.
Boundary objects are used for transferring data across module boundaries, and are used for building interfaces between parts of the system, which should be decoupled from one-another. For example, a controller may need to create a Purchase_Book object, and in order to create it, it needs to pass data about what book ID needs to be purchased, by what user ID, etc... and this data can be packed in a boundary object called Purchase_Request.
While Interactor and Boundary require more explanation, I find that the word Entities is meaningful and can be grasped intuitively without reading any explanation.
I have a server which stores records representing Objects, and which uses Mongoose to manage these records. I want to be able to query/update/etc. all objects with a simple API (i.e. a single endpoint). Different types of Objects have some identical attributes, and some different attributes, so a single, static Object schema won't do. Instead, I still want to have a single schema, but I want to be able to change it slightly by adding/deleting fields when I create each new Object, with the fields which are/aren't present depending on the type of the Object. I don't want a mixed schema, because I want error validation for each type of Object. I want a single schema (as opposed to a different schema for each type of Object) so that I can just do
Object = mongoose.model('Object', ObjectSchema);
Object.findOne({objectType: "type1"}, function(err, model) {
...
});
So basically, I want field validation, while still maintaining some flexibility for attributes, and a single point to query/update/etc. my Object records. If I change the schema with each new Object, recompile it into a model, and create a new instance of that model, will all the instances of the different models (compiled from different modified versions of the same schema) still be queryable as above?
Obviously, I'm new to Mongoose. I just talked a lot about the schema here, and I honestly don't know whether I should have used the word "model" in place of "schema" in some places. I just don't know how I can accomplish all of this. Let me know if I make no sense.
We are successfully using the mongoose model inheritance and discriminator functionality for a very similar scenario. See here for an example:
http://www.laplacesdemon.com/2014/02/19/model-inheritance-node-js-mongoose/
You might also be able to use this plugin:
https://www.npmjs.com/package/mongoose-schema-extend