Develop a Function to Read a Document in the Mongodb Database

Limited Tutorial Role 3: Using a Database (with Mongoose)

  • Previous
  • Overview: Express Nodejs
  • Adjacent

This article briefly introduces databases, and how to utilize them with Node/Express apps. It then goes on to show how we can use Mongoose to provide database admission for the LocalLibrary website. Information technology explains how object schema and models are declared, the principal field types, and basic validation. It as well briefly shows a few of the main means in which you can access model data.

Prerequisites: Express Tutorial Part two: Creating a skeleton website
Objective: To be able to design and create your own models using Mongoose.

Library staff will use the Local Library website to store information about books and borrowers, while library members will utilise it to browse and search for books, find out whether there are any copies available, and so reserve or borrow them. In order to store and retrieve information efficiently, we will store it in a database.

Limited apps can use many different databases, and there are several approaches yous can apply for performing Create, Read, Update and Delete (Grime) operations. This tutorial provides a cursory overview of some of the available options and then goes on to prove in detail the item mechanisms selected.

What databases can I apply?

Express apps can use any database supported by Node (Express itself doesn't ascertain any specific additional behavior/requirements for database management). There are many popular options, including PostgreSQL, MySQL, Redis, SQLite, and MongoDB.

When choosing a database, you lot should consider things like time-to-productivity/learning curve, performance, ease of replication/backup, toll, community back up, etc. While there is no unmarried "all-time" database, near any of the popular solutions should be more than acceptable for a modest-to-medium-sized site like our Local Library.

For more data on the options see Database integration (Express docs).

What is the best way to collaborate with a database?

There are ii common approaches for interacting with a database:

  • Using the databases' native query language (e.g. SQL)
  • Using an Object Data Model ("ODM") or an Object Relational Model ("ORM"). An ODM/ORM represents the website'southward data equally JavaScript objects, which are and then mapped to the underlying database. Some ORMs are tied to a specific database, while others provide a database-agnostic backend.

The very best performance can exist gained by using SQL, or whatever query language is supported past the database. ODM'due south are often slower because they use translation code to map between objects and the database format, which may not use the most efficient database queries (this is especially true if the ODM supports different database backends, and must make greater compromises in terms of what database features are supported).

The benefit of using an ORM is that programmers can continue to think in terms of JavaScript objects rather than database semantics — this is peculiarly true if you need to piece of work with unlike databases (on either the same or unlike websites). They also provide an obvious place to perform information validation.

Note: Using ODM/ORMs oftentimes results in lower costs for development and maintenance! Unless you're very familiar with the native query linguistic communication or performance is paramount, y'all should strongly consider using an ODM.

What ORM/ODM should I utilise?

There are many ODM/ORM solutions available on the NPM package director site (bank check out the odm and orm tags for a subset!).

A few solutions that were popular at the fourth dimension of writing are:

  • Mongoose: Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
  • Waterline: An ORM extracted from the Express-based Sails web framework. It provides a compatible API for accessing numerous different databases, including Redis, MySQL, LDAP, MongoDB, and Postgres.
  • Bookshelf: Features both hope-based and traditional callback interfaces, providing transaction support, eager/nested-eager relation loading, polymorphic associations, and back up for one-to-one, one-to-many, and many-to-many relations. Works with PostgreSQL, MySQL, and SQLite3.
  • Objection: Makes information technology as like shooting fish in a barrel as possible to use the full power of SQL and the underlying database engine (supports SQLite3, Postgres, and MySQL).
  • Sequelize is a promise-based ORM for Node.js and io.js. It supports the dialects PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL and features solid transaction support, relations, read replication and more.
  • Node ORM2 is an Object Relationship Managing director for NodeJS. It supports MySQL, SQLite, and Progress, helping to work with the database using an object-oriented approach.
  • GraphQL: Primarily a query language for restful APIs, GraphQL is very pop, and has features available for reading data from databases.

Every bit a general rule, yous should consider both the features provided and the "customs action" (downloads, contributions, bug reports, quality of documentation, etc.) when selecting a solution. At the time of writing Mongoose is by far the virtually popular ODM, and is a reasonable choice if you're using MongoDB for your database.

Using Mongoose and MongoDb for the LocalLibrary

For the Local Library example (and the residual of this topic) nosotros're going to use the Mongoose ODM to access our library data. Mongoose acts as a front end to MongoDB, an open source NoSQL database that uses a certificate-oriented information model. A "collection" of "documents" in a MongoDB database is analogous to a "table" of "rows" in a relational database.

This ODM and database combination is extremely popular in the Node customs, partially considering the document storage and query organization looks very much similar JSON, and is hence familiar to JavaScript developers.

Note: You don't demand to know MongoDB in lodge to use Mongoose, although parts of the Mongoose documentation are easier to employ and understand if you are already familiar with MongoDB.

The rest of this tutorial shows how to define and access the Mongoose schema and models for the LocalLibrary website case.

Designing the LocalLibrary models

Earlier you jump in and starting time coding the models, it's worth taking a few minutes to think about what information we need to store and the relationships between the different objects.

We know that we need to shop information about books (title, summary, author, genre, ISBN) and that nosotros might accept multiple copies available (with globally unique ids, availability statuses, etc.). We might need to store more information most the author than just their proper name, and in that location might be multiple authors with the same or similar names. We want to be able to sort information based on the volume title, author, genre, and category.

When designing your models it makes sense to take carve up models for every "object" (a grouping of related information). In this case some obvious candidates for these models are books, book instances, and authors.

You lot might also want to use models to represent option-listing options (e.thou. like a drop-downwardly list of choices), rather than hard-coding the choices into the website itself — this is recommended when all the options aren't known upwards forepart or may change. A good example is a genre (e.thousand. fantasy, science fiction, etc.).

Once nosotros've decided on our models and fields, we need to think about the relationships between them.

With that in listen, the UML association diagram below shows the models we'll define in this instance (as boxes). As discussed above, we've created models for the book (the generic details of the book), book instance (status of specific physical copies of the volume available in the system), and author. We take also decided to accept a model for the genre so that values can be created dynamically. We've decided not to have a model for the BookInstance:status — we will hard code the acceptable values because we don't expect these to change. Within each of the boxes, yous can see the model name, the field names and types, and also the methods and their return types.

The diagram also shows the relationships between the models, including their multiplicities. The multiplicities are the numbers on the diagram showing the numbers (maximum and minimum) of each model that may exist present in the relationship. For example, the connecting line betwixt the boxes shows that Book and a Genre are related. The numbers close to the Book model show that a Genre must have zero or more Books (every bit many as you similar), while the numbers on the other end of the line next to the Genre show that a book can have zero or more associated Genres.

Note: As discussed in our Mongoose primer beneath it is often better to take the field that defines the human relationship betwixt the documents/models in but 1 model (y'all tin can still find the contrary relationship by searching for the associated _id in the other model). Below we have called to define the relationship between Volume/Genre and Volume/Writer in the Book schema, and the relationship between the Book/BookInstance in the BookInstance Schema. This selection was somewhat arbitrary — we could as well have had the field in the other schema.

Mongoose Library Model  with correct cardinality

Note: The side by side section provides a basic primer explaining how models are defined and used. As you read information technology, consider how we will construct each of the models in the diagram above.

Mongoose primer

This department provides an overview of how to connect Mongoose to a MongoDB database, how to define a schema and a model, and how to make bones queries.

Installing Mongoose and MongoDB

Mongoose is installed in your projection (packet.json) similar any other dependency — using NPM. To install it, employ the following command inside your project folder:

Installing Mongoose adds all its dependencies, including the MongoDB database driver, but it does not install MongoDB itself. If yous want to install a MongoDB server so you lot can download installers from here for various operating systems and install it locally. You can also use cloud-based MongoDB instances.

Note: For this tutorial, we'll be using the MongoDB Atlas deject-based database every bit a service free tier to provide the database. This is suitable for evolution and makes sense for the tutorial because it makes "installation" operating system independent (database-every bit-a-service is also one approach you might use for your product database).

Connecting to MongoDB

Mongoose requires a connection to a MongoDB database. You tin can require() and connect to a locally hosted database with mongoose.connect(), as shown below.

                                  //Import the mongoose module                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  //Set upwards default mongoose connection                  var                  mongoDB                  =                  'mongodb://127.0.0.1/my_database'                  ;                  mongoose.                  connect                  (mongoDB,                  {                  useNewUrlParser                  :                  true                  ,                  useUnifiedTopology                  :                  true                  }                  )                  ;                  //Get the default connectedness                  var                  db                  =                  mongoose.connection;                  //Demark connexion to fault effect (to get notification of connection errors)                  db.                  on                  (                  'error'                  ,                  console.                  error                  .                  bind                  (panel,                  'MongoDB connexion error:'                  )                  )                  ;                              

You lot tin become the default Connection object with mongoose.connection. Once connected, the open upshot is fired on the Connection case.

Note: If y'all need to create additional connections you lot can use mongoose.createConnection(). This takes the same grade of database URI (with host, database, port, options etc.) equally connect() and returns a Connection object).

Defining and creating models

Models are defined using the Schema interface. The Schema allows you to define the fields stored in each certificate forth with their validation requirements and default values. In addition, you can define static and instance helper methods to make information technology easier to work with your data types, and also virtual properties that you can use like any other field, but which aren't actually stored in the database (we'll talk over a bit further beneath).

Schemas are and then "compiled" into models using the mongoose.model() method. Once y'all have a model you can use it to observe, create, update, and delete objects of the given type.

Note: Each model maps to a collection of documents in the MongoDB database. The documents will contain the fields/schema types defined in the model Schema.

Defining schemas

The code fragment below shows how you lot might ascertain a unproblematic schema. Start y'all require() mongoose, then use the Schema constructor to create a new schema example, defining the various fields within information technology in the constructor's object parameter.

                                  //Require Mongoose                  var                  mongoose                  =                  crave                  (                  'mongoose'                  )                  ;                  //Define a schema                  var                  Schema                  =                  mongoose.Schema;                  var                  SomeModelSchema                  =                  new                  Schema                  (                  {                  a_string                  :                  Cord,                  a_date                  :                  Date                  }                  )                  ;                              

In the case above we just have two fields, a string and a engagement. In the side by side sections, we volition show some of the other field types, validation, and other methods.

Creating a model

Models are created from schemas using the mongoose.model() method:

                                  // Define schema                  var                  Schema                  =                  mongoose.Schema;                  var                  SomeModelSchema                  =                  new                  Schema                  (                  {                  a_string                  :                  Cord,                  a_date                  :                  Date                  }                  )                  ;                  // Compile model from schema                  var                  SomeModel                  =                  mongoose.                  model                  (                  'SomeModel'                  ,                  SomeModelSchema                  )                  ;                              

The offset argument is the singular proper name of the collection that volition be created for your model (Mongoose volition create the database collection for the to a higher place model SomeModel in a higher place), and the 2d argument is the schema you lot want to utilize in creating the model.

Note: Once you've divers your model classes you tin utilize them to create, update, or delete records, and run queries to get all records or particular subsets of records. Nosotros'll prove y'all how to practice this in the Using models department, and when we create our views.

Schema types (fields)

A schema tin can have an arbitrary number of fields — each one represents a field in the documents stored in MongoDB. An example schema showing many of the common field types and how they are declared is shown below.

                                  var                  schema                  =                  new                  Schema                  (                  {                  proper noun                  :                  String,                  binary                  :                  Buffer,                  living                  :                  Boolean,                  updated                  :                  {                  type                  :                  Date,                  default                  :                  Date.                  now                  (                  )                  }                  ,                  historic period                  :                  {                  type                  :                  Number,                  min                  :                  18                  ,                  max                  :                  65                  ,                  required                  :                  true                  }                  ,                  mixed                  :                  Schema.Types.Mixed,                  _someId                  :                  Schema.Types.ObjectId,                  assortment                  :                  [                  ]                  ,                  ofString                  :                  [String]                  ,                  // You can also have an array of each of the other types also.                  nested                  :                  {                  stuff                  :                  {                  type                  :                  Cord,                  lowercase                  :                  true                  ,                  trim                  :                  true                  }                  }                  }                  )                              

Most of the SchemaTypes (the descriptors after "type:" or afterward field names) are self-explanatory. The exceptions are:

  • ObjectId: Represents specific instances of a model in the database. For example, a volume might use this to represent its author object. This will really contain the unique ID (_id) for the specified object. We tin can utilize the populate() method to pull in the associated data when needed.
  • Mixed: An arbitrary schema type.
  • []: An assortment of items. You tin perform JavaScript assortment operations on these models (push button, popular, unshift, etc.). The examples above show an array of objects without a specified type and an array of String objects, but you can have an array of whatever blazon of object.

The code also shows both ways of declaring a field:

  • Field name and blazon as a key-value pair (i.e. as done with fields proper name, binary and living).
  • Field proper name followed by an object defining the type, and any other options for the field. Options include things like:
    • default values.
    • congenital-in validators (e.g. max/min values) and custom validation functions.
    • Whether the field is required
    • Whether Cord fields should automatically exist prepare to lowercase, capital letter, or trimmed (east.thousand. { blazon: Cord, lowercase: true, trim: truthful })

For more information about options see SchemaTypes (Mongoose docs).

Validation

Mongoose provides born and custom validators, and synchronous and asynchronous validators. Information technology allows y'all to specify both the acceptable range of values and the fault message for validation failure in all cases.

The born validators include:

  • All SchemaTypes have the congenital-in required validator. This is used to specify whether the field must be supplied in order to save a certificate.
  • Numbers have min and max validators.
  • Strings take:
    • enum: specifies the prepare of immune values for the field.
    • match: specifies a regular expression that the string must match.
    • maxLength and minLength for the string.

The example beneath (slightly modified from the Mongoose documents) shows how you tin specify some of the validator types and error messages:

                                  var                  breakfastSchema                  =                  new                  Schema                  (                  {                  eggs                  :                  {                  type                  :                  Number,                  min                  :                  [                  6                  ,                  'Too few eggs'                  ]                  ,                  max                  :                  12                  ,                  required                  :                  [                  true                  ,                  'Why no eggs?'                  ]                  }                  ,                  potable                  :                  {                  type                  :                  String,                  enum                  :                  [                  'Coffee'                  ,                  'Tea'                  ,                  'H2o'                  ,                  ]                  }                  }                  )                  ;                              

For complete information on field validation encounter Validation (Mongoose docs).

Virtual properties

Virtual backdrop are document properties that y'all tin can get and set but that do not become persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage. The example in the documentation constructs (and deconstructs) a full name virtual belongings from a first and last name field, which is easier and cleaner than constructing a full name every time one is used in a template.

Note: We will use a virtual property in the library to define a unique URL for each model record using a path and the record'south _id value.

For more than information encounter Virtuals (Mongoose documentation).

Methods and query helpers

A schema tin as well have instance methods, static methods, and query helpers. The instance and static methods are similar, but with the obvious difference that an example method is associated with a particular record and has access to the current object. Query helpers let you to extend mongoose's chainable query architect API (for example, allowing you to add a query "byName" in addition to the find(), findOne() and findById() methods).

Using models

Once you've created a schema you can use it to create models. The model represents a collection of documents in the database that you tin search, while the model's instances represent individual documents that y'all tin can save and recall.

We provide a brief overview below. For more information see: Models (Mongoose docs).

Creating and modifying documents

To create a record you lot can define an instance of the model and then call save(). The examples below assume SomeModel is a model (with a unmarried field "proper noun") that we have created from our schema.

                                  // Create an case of model SomeModel                  var                  awesome_instance                  =                  new                  SomeModel                  (                  {                  name                  :                  'awesome'                  }                  )                  ;                  // Save the new model instance, passing a callback                  awesome_instance.                  salve                  (                  function                  (                  err                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // saved!                  }                  )                  ;                              

Creation of records (along with updates, deletes, and queries) are asynchronous operations — you supply a callback that is called when the operation completes. The API uses the error-first statement convention, so the beginning statement for the callback will always exist an error value (or cypher). If the API returns some effect, this volition be provided every bit the second argument.

You tin also use create() to define the model instance at the same time as y'all save information technology. The callback volition return an error for the get-go argument and the newly-created model instance for the second argument.

                SomeModel.                  create                  (                  {                  name                  :                  'also_awesome'                  }                  ,                  function                  (                  err,                    awesome_instance                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // saved!                  }                  )                  ;                              

Every model has an associated connection (this volition be the default connection when you use mongoose.model()). You create a new connectedness and telephone call .model() on it to create the documents on a different database.

You lot can admission the fields in this new record using the dot syntax, and modify the values. You accept to call save() or update() to store modified values back to the database.

                                  // Admission model field values using dot notation                  console.                  log                  (awesome_instance.proper noun)                  ;                  //should log 'also_awesome'                  // Change record by modifying the fields, then calling salvage().                  awesome_instance.name=                  "New cool name"                  ;                  awesome_instance.                  save                  (                  part                  (                  err                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // saved!                  }                  )                  ;                              

Searching for records

Yous can search for records using query methods, specifying the query weather condition as a JSON document. The lawmaking fragment below shows how you might notice all athletes in a database that play tennis, returning just the fields for athlete name and age. Here we but specify one matching field (sport) simply yous can add more criteria, specify regular expression criteria, or remove the conditions altogether to return all athletes.

                                  var                  Athlete                  =                  mongoose.                  model                  (                  'Athlete'                  ,                  yourSchema)                  ;                  // find all athletes who play tennis, selecting the 'name' and 'age' fields                  Athlete.                  find                  (                  {                  'sport'                  :                  'Tennis'                  }                  ,                  'name historic period'                  ,                  function                  (                  err,                    athletes                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // 'athletes' contains the list of athletes that match the criteria.                  }                  )                              

If you specify a callback, as shown in a higher place, the query volition execute immediately. The callback will exist invoked when the search completes.

Note: All callbacks in Mongoose utilize the blueprint callback(error, consequence). If an error occurs executing the query, the error parameter will comprise an error certificate and result will be null. If the query is successful, the mistake parameter will be cipher, and the effect will exist populated with the results of the query.

Notation: It is important to remember that not finding whatever results is not an mistake for a search —but it may be a neglect-case in the context of your awarding. If your application expects a search to find a value yous tin either check the upshot in the callback (results==null) or daisy chain the orFail() method on the query.

If you don't specify a callback then the API volition return a variable of type Query. You can use this query object to build up your query then execute it (with a callback) afterward using the exec() method.

                                  // discover all athletes that play tennis                  var                  query                  =                  Athlete.                  find                  (                  {                  'sport'                  :                  'Tennis'                  }                  )                  ;                  // selecting the 'proper noun' and 'age' fields                  query.                  select                  (                  'proper noun age'                  )                  ;                  // limit our results to 5 items                  query.                  limit                  (                  v                  )                  ;                  // sort past historic period                  query.                  sort                  (                  {                  historic period                  :                  -                  1                  }                  )                  ;                  // execute the query at a later fourth dimension                  query.                  exec                  (                  function                  (                  err,                    athletes                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // athletes contains an ordered list of 5 athletes who play Tennis                  }                  )                              

Above we've defined the query conditions in the notice() method. We can as well practice this using a where() role, and we tin can chain all the parts of our query together using the dot operator (.) rather than calculation them separately. The code fragment below is the same equally our query higher up, with an boosted condition for the age.

                Athlete.                  find                  (                  )                  .                  where                  (                  'sport'                  )                  .                  equals                  (                  'Tennis'                  )                  .                  where                  (                  'historic period'                  )                  .                  gt                  (                  17                  )                  .                  lt                  (                  50                  )                  .                  //Additional where query                  limit                  (                  5                  )                  .                  sort                  (                  {                  age                  :                  -                  one                  }                  )                  .                  select                  (                  'name historic period'                  )                  .                  exec                  (callback)                  ;                  // where callback is the name of our callback function.                              

The find() method gets all matching records, just ofttimes y'all only want to get i lucifer. The following methods query for a unmarried record:

  • findById(): Finds the document with the specified id (every document has a unique id).
  • findOne(): Finds a unmarried document that matches the specified criteria.
  • findByIdAndRemove(), findByIdAndUpdate(), findOneAndRemove(), findOneAndUpdate(): Finds a single document by id or criteria and either updates or removes information technology. These are useful convenience functions for updating and removing records.

Note: There is as well a count() method that you can employ to get the number of items that friction match conditions. This is useful if you want to perform a count without actually fetching the records.

At that place is a lot more you tin can practice with queries. For more information come across: Queries (Mongoose docs).

You tin create references from one document/model example to another using the ObjectId schema field, or from 1 document to many using an array of ObjectIds. The field stores the id of the related model. If you need the actual content of the associated certificate, you tin use the populate() method in a query to replace the id with the bodily data.

For example, the post-obit schema defines authors and stories. Each author can take multiple stories, which we represent equally an array of ObjectId. Each story can have a single author. The ref property tells the schema which model tin can be assigned to this field.

                                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ,                  Schema                  =                  mongoose.Schema                  var                  authorSchema                  =                  Schema                  (                  {                  proper noun                  :                  String,                  stories                  :                  [                  {                  blazon                  :                  Schema.Types.ObjectId,                  ref                  :                  'Story'                  }                  ]                  }                  )                  ;                  var                  storySchema                  =                  Schema                  (                  {                  author                  :                  {                  type                  :                  Schema.Types.ObjectId,                  ref                  :                  'Writer'                  }                  ,                  title                  :                  Cord                  }                  )                  ;                  var                  Story                  =                  mongoose.                  model                  (                  'Story'                  ,                  storySchema)                  ;                  var                  Author                  =                  mongoose.                  model                  (                  'Author'                  ,                  authorSchema)                  ;                              

We can save our references to the related document by assigning the _id value. Below nosotros create an writer, so a story, and assign the writer id to our story'south writer field.

                                  var                  bob                  =                  new                  Writer                  (                  {                  name                  :                  'Bob Smith'                  }                  )                  ;                  bob.                  salve                  (                  function                  (                  err                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  //Bob at present exists, then lets create a story                  var                  story                  =                  new                  Story                  (                  {                  title                  :                  "Bob goes sledding"                  ,                  author                  :                  bob._id                  // assign the _id from our writer Bob. This ID is created by default!                  }                  )                  ;                  story.                  save                  (                  function                  (                  err                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  // Bob at present has his story                  }                  )                  ;                  }                  )                  ;                              

Our story certificate at present has an author referenced by the author document's ID. In gild to become the author information in the story results we use populate(), as shown below.

                Story                  .                  findOne                  (                  {                  title                  :                  'Bob goes sledding'                  }                  )                  .                  populate                  (                  'author'                  )                  //This populates the author id with bodily author information!                  .                  exec                  (                  function                  (                  err,                    story                  )                  {                  if                  (err)                  return                  handleError                  (err)                  ;                  panel.                  log                  (                  'The writer is %s'                  ,                  story.author.name)                  ;                  // prints "The writer is Bob Smith"                  }                  )                  ;                              

Notation: Astute readers will have noted that nosotros added an author to our story, merely we didn't practise anything to add our story to our author's stories array. How then tin can we get all stories by a particular author? One manner would exist to add together our story to the stories array, but this would result in us having two places where the information relating authors and stories needs to be maintained.

A better style is to become the _id of our writer, then use find() to search for this in the writer field across all stories.

                  Story                    .                    find                    (                    {                    author                    :                    bob._id                    }                    )                    .                    exec                    (                    function                    (                    err,                      stories                    )                    {                    if                    (err)                    render                    handleError                    (err)                    ;                    // returns all stories that have Bob's id as their author.                    }                    )                    ;                                  

This is well-nigh everything y'all need to know near working with related items for this tutorial. For more detailed data run across Population (Mongoose docs).

I schema/model per file

While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its ain module (file), then exporting the method to create the model. This is shown below:

                                  // File: ./models/somemodel.js                  //Crave Mongoose                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  //Ascertain a schema                  var                  Schema                  =                  mongoose.Schema;                  var                  SomeModelSchema                  =                  new                  Schema                  (                  {                  a_string                  :                  Cord,                  a_date                  :                  Date,                  }                  )                  ;                  //Export role to create "SomeModel" model class                  module.exports                  =                  mongoose.                  model                  (                  'SomeModel'                  ,                  SomeModelSchema                  )                  ;                              

You can then require and use the model immediately in other files. Below we bear witness how yous might use information technology to become all instances of the model.

                                  //Create a SomeModel model simply by requiring the module                  var                  SomeModel                  =                  require                  (                  '../models/somemodel'                  )                  // Use the SomeModel object (model) to find all SomeModel records                  SomeModel.                  discover                  (callback_function)                  ;                              

Setting upward the MongoDB database

At present that we sympathize something of what Mongoose can do and how we want to pattern our models, it's time to showtime piece of work on the LocalLibrary website. The very first matter we want to practise is set a MongoDB database that we can utilize to store our library data.

For this tutorial, nosotros're going to employ the MongoDB Atlas gratis deject-hosted sandbox database. This database tier is not considered suitable for production websites because information technology has no redundancy, but it is corking for development and prototyping. Nosotros're using it here because it is free and easy to set up, and because MongoDB Atlas is a popular database as a service vendor that y'all might reasonably cull for your production database (other popular choices at the time of writing include Etch, ScaleGrid and ObjectRocket).

Note: If y'all prefer you can gear up up a MongoDb database locally by downloading and installing the appropriate binaries for your system. The residuum of the instructions in this article would be similar, except for the database URL you would specify when connecting. Annotation, still, that the Limited Tutorial Part vii: Deploying to Production tutorial requires some form of remote database, since the free tier of the Heroku service does not provide persistent storage. Information technology is therefore highly recommended to use MongoDB Atlas.

You will starting time need to create an business relationship with MongoDB Atlas (this is free, and just requires that y'all enter basic contact details and acknowledge their terms of service).

After logging in, you'll exist taken to the habitation screen:

  1. Click Build a Cluster button in the Clusters Overview section. Create a cluster on MongoDB Atlas.
  2. This will open the Create New Cluster screen. Choose a cloud provider when using MongoDB Atlas.
    • Select any provider from the Cloud Provider & Region department. Different providers offer different regions.
    • Select any region marked "FREE TIER AVAILABLE".
    • Click the Create Cluster push button (creation of the cluster will take some minutes).
  3. You will return to the Cluster Overview screen. Setup a collection on MongoDB Atlas.
    • Click the Collections push button.
  4. This will open the Collections section. Create a database on MongoDB Atlas.
    • Click the Add My Own Data button.
  5. This volition open up the Create Database screen. Details during database creation on MongoDB Atlas.
    • Enter the name for the new database equally local_library.
    • Enter the proper noun of the collection every bit Collection0.
    • Click the Create push to create the database.
  6. You will return to the Collection screen with your database created. Database creation confirmation on MongoDB Atlas.
    • Click the Overview tab to return the cluster overview.
  7. From the Cluster0 Overview screen click the Connect button. Configure a connection when after setting up a cluster in MongoDB Atlas.
  8. This volition open up the Connect to Cluster screen. Choose a connection type when connecting with MongoDB Atlas.
    • Click the Allow Access from Anywhere button. This will open a grade with 0.0.0.0/0 pre-seeded for the IP Address. Click the Add IP Accost push.

      Annotation: Information technology is a all-time do to limit the IP addresses that can connect to your database and other resources. Here we allow a connectedness from anywhere because we don't know where the request will come from after deployment.

    • Enter a username and countersign and click Create MongoDB User button.

      Note: Avoid using special characters in your MongoDB user password as mongoose may not parse the connection cord properly.

    • If you have completed the two previous steps, the push button Choose a connectedness method will turn green.
    • Click the Choose a connexion method button.
  9. You should at present exist able to access the Choose a connection method tab. Choose a connection type when connecting with MongoDB Atlas.
    • Click the Connect Your Application option.
  10. This will open the Connect screen. Choose the Short SRV connection when setting up a connection on MongoDB Atlas.
    • Click the Copy push to copy the connection string.
    • Save this string somewhere safe.
    • Update the password with your user's password.
    • Replace test with local_library.

Yous accept at present created the database, and accept a URL (with username and password) that tin be used to admission it. This will look something like: mongodb+srv://your_user_name:your_password@cluster0.a9azn.mongodb.cyberspace/local_library?retryWrites=true

Install Mongoose

Open up a command prompt and navigate to the directory where you created your skeleton Local Library website. Enter the post-obit control to install Mongoose (and its dependencies) and add information technology to your parcel.json file, unless you have already washed so when reading the Mongoose Primer above.

Connect to MongoDB

Open /app.js (in the root of your project) and re-create the following text below where you declare the Express application object (later the line var app = express();). Supervene upon the database url string ('insert_your_database_url_here') with the location URL representing your own database (i.due east. using the information from mongoDB Atlas).

                                  //Ready upwardly mongoose connection                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  var                  mongoDB                  =                  'insert_your_database_url_here'                  ;                  mongoose.                  connect                  (mongoDB,                  {                  useNewUrlParser                  :                  true                  ,                  useUnifiedTopology                  :                  true                  }                  )                  ;                  var                  db                  =                  mongoose.connection;                  db.                  on                  (                  'error'                  ,                  console.                  error                  .                  bind                  (console,                  'MongoDB connection error:'                  )                  )                  ;                              

Every bit discussed in the Mongoose primer above, this code creates the default connection to the database and binds to the fault event (and then that errors volition be printed to the console).

Defining the LocalLibrary Schema

We volition define a separate module for each model, equally discussed higher up. Start past creating a binder for our models in the project root (/models) and so create carve up files for each of the models:

/limited-locallibrary-tutorial  //the project root   /models     author.js     book.js     bookinstance.js     genre.js              

Copy the Author schema lawmaking shown beneath and paste it into your ./models/writer.js file. The schema defines an author every bit having String SchemaTypes for the showtime and family names (required, with a maximum of 100 characters), and Date fields for the dates of birth and expiry.

                                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  var                  Schema                  =                  mongoose.Schema;                  var                  AuthorSchema                  =                  new                  Schema                  (                  {                  first_name                  :                  {                  blazon                  :                  Cord,                  required                  :                  true                  ,                  maxLength                  :                  100                  }                  ,                  family_name                  :                  {                  type                  :                  String,                  required                  :                  true                  ,                  maxLength                  :                  100                  }                  ,                  date_of_birth                  :                  {                  type                  :                  Engagement}                  ,                  date_of_death                  :                  {                  type                  :                  Date}                  ,                  }                  )                  ;                  // Virtual for author's full name                  AuthorSchema                  .                  virtual                  (                  'name'                  )                  .                  get                  (                  part                  (                  )                  {                  // To avoid errors in cases where an author does non accept either a family proper noun or first name                  // Nosotros desire to make sure we handle the exception by returning an empty string for that instance                  var                  fullname                  =                  ''                  ;                  if                  (                  this                  .first_name                  &&                  this                  .family_name)                  {                  fullname                  =                  this                  .family_name                  +                  ', '                  +                  this                  .first_name                  }                  if                  (                  !                  this                  .first_name                  ||                  !                  this                  .family_name)                  {                  fullname                  =                  ''                  ;                  }                  return                  fullname;                  }                  )                  ;                  // Virtual for author's lifespan                  AuthorSchema.                  virtual                  (                  'lifespan'                  )                  .                  get                  (                  function                  (                  )                  {                  var                  lifetime_string                  =                  ''                  ;                  if                  (                  this                  .date_of_birth)                  {                  lifetime_string                  =                  this                  .date_of_birth.                  getYear                  (                  )                  .                  toString                  (                  )                  ;                  }                  lifetime_string                  +=                  ' - '                  ;                  if                  (                  this                  .date_of_death)                  {                  lifetime_string                  +=                  this                  .date_of_death.                  getYear                  (                  )                  }                  return                  lifetime_string;                  }                  )                  ;                  // Virtual for author'due south URL                  AuthorSchema                  .                  virtual                  (                  'url'                  )                  .                  go                  (                  function                  (                  )                  {                  return                  '/catalog/author/'                  +                  this                  ._id;                  }                  )                  ;                  //Consign model                  module.exports                  =                  mongoose.                  model                  (                  'Writer'                  ,                  AuthorSchema)                  ;                              

Nosotros've also declared a virtual for the AuthorSchema named "url" that returns the accented URL required to get a item instance of the model — nosotros'll use the property in our templates whenever we demand to get a link to a detail author.

Note: Declaring our URLs as a virtual in the schema is a good idea because then the URL for an item only ever needs to be inverse in i place. At this point, a link using this URL wouldn't piece of work, because we haven't got any routes treatment lawmaking for individual model instances. We'll set those up in a later article!

At the end of the module, we export the model.

Book model

Copy the Book schema lawmaking shown below and paste it into your ./models/book.js file. Most of this is similar to the author model — we've declared a schema with a number of string fields and a virtual for getting the URL of specific book records, and we've exported the model.

                                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  var                  Schema                  =                  mongoose.Schema;                  var                  BookSchema                  =                  new                  Schema                  (                  {                  title                  :                  {                  type                  :                  Cord,                  required                  :                  truthful                  }                  ,                  author                  :                  {                  type                  :                  Schema.Types.ObjectId,                  ref                  :                  'Writer'                  ,                  required                  :                  true                  }                  ,                  summary                  :                  {                  type                  :                  String,                  required                  :                  true                  }                  ,                  isbn                  :                  {                  blazon                  :                  String,                  required                  :                  truthful                  }                  ,                  genre                  :                  [                  {                  type                  :                  Schema.Types.ObjectId,                  ref                  :                  'Genre'                  }                  ]                  }                  )                  ;                  // Virtual for book's URL                  BookSchema                  .                  virtual                  (                  'url'                  )                  .                  get                  (                  office                  (                  )                  {                  return                  '/catalog/book/'                  +                  this                  ._id;                  }                  )                  ;                  //Export model                  module.exports                  =                  mongoose.                  model                  (                  'Book'                  ,                  BookSchema)                  ;                              

The chief difference here is that we've created ii references to other models:

  • writer is a reference to a single Author model object, and is required.
  • genre is a reference to an assortment of Genre model objects. We haven't alleged this object still!

BookInstance model

Finally, re-create the BookInstance schema code shown below and paste it into your ./models/bookinstance.js file. The BookInstance represents a specific re-create of a book that someone might borrow and includes data about whether the copy is available, on what date it is expected back, and "imprint" (or version) details.

                                  var                  mongoose                  =                  require                  (                  'mongoose'                  )                  ;                  var                  Schema                  =                  mongoose.Schema;                  var                  BookInstanceSchema                  =                  new                  Schema                  (                  {                  book                  :                  {                  type                  :                  Schema.Types.ObjectId,                  ref                  :                  'Volume'                  ,                  required                  :                  true                  }                  ,                  //reference to the associated book                  banner                  :                  {                  type                  :                  Cord,                  required                  :                  true                  }                  ,                  status                  :                  {                  type                  :                  String,                  required                  :                  truthful                  ,                  enum                  :                  [                  'Bachelor'                  ,                  'Maintenance'                  ,                  'Loaned'                  ,                  'Reserved'                  ]                  ,                  default                  :                  'Maintenance'                  }                  ,                  due_back                  :                  {                  type                  :                  Date,                  default                  :                  Date.now}                  }                  )                  ;                  // Virtual for bookinstance's URL                  BookInstanceSchema                  .                  virtual                  (                  'url'                  )                  .                  get                  (                  function                  (                  )                  {                  return                  '/itemize/bookinstance/'                  +                  this                  ._id;                  }                  )                  ;                  //Export model                  module.exports                  =                  mongoose.                  model                  (                  'BookInstance'                  ,                  BookInstanceSchema)                  ;                              

The new things nosotros show here are the field options:

  • enum: This allows us to gear up the allowed values of a string. In this case, we use it to specify the availability status of our books (using an enum means that nosotros can prevent mis-spellings and arbitrary values for our status).
  • default: We use default to gear up the default status for newly created bookinstances to maintenance and the default due_back date to now (annotation how you can phone call the Date function when setting the date!).

Everything else should exist familiar from our previous schema.

Genre model - challenge!

Open your ./models/genre.js file and create a schema for storing genres (the category of book, e.g. whether it is fiction or non-fiction, romance or armed services history, etc).

The definition will be very similar to the other models:

  • The model should have a String SchemaType called name to describe the genre.
  • This proper name should be required and have between iii and 100 characters.
  • Declare a virtual for the genre's URL, named url.
  • Export the model.

Testing — create some items

That's it. We at present have all models for the site set!

In order to exam the models (and to create some case books and other items that nosotros can use in our next articles) we'll now run an contained script to create items of each type:

  1. Download (or otherwise create) the file populatedb.js within your express-locallibrary-tutorial directory (in the same level as package.json).

    Note: You don't need to know how populatedb.js works; it just adds sample data into the database.

  2. Enter the post-obit commands in the project root to install the async module that is required by the script (we'll hash out this in subsequently tutorials, )
  3. Run the script using node in your control prompt, passing in the URL of your MongoDB database (the same ane you replaced the insert_your_database_url_here placeholder with, inside app.js earlier):
                                              node                      populatedb                      <your mongodb url>                                      

    Note: On some operating systems/terminals, you may need to wrap the database URL inside double (") or single (') quotation marks.

  4. The script should run through to completion, displaying items as it creates them in the final.

Note: Go to your database on mongoDB Atlas (in the Collections tab). Y'all should now be able to drill downwardly into individual collections of Books, Authors, Genres and BookInstances, and bank check out individual documents.

Summary

In this article, nosotros've learned a bit near databases and ORMs on Node/Limited, and a lot about how Mongoose schema and models are defined. We and so used this data to design and implement Book, BookInstance, Writer and Genre models for the LocalLibrary website.

Final of all, we tested our models by creating a number of instances (using a standalone script). In the next commodity we'll look at creating some pages to display these objects.

Encounter also

In this module

  • Express/Node introduction
  • Setting up a Node (Express) development environment
  • Express Tutorial: The Local Library website
  • Express Tutorial Function two: Creating a skeleton website
  • Limited Tutorial Part 3: Using a Database (with Mongoose)
  • Express Tutorial Part four: Routes and controllers
  • Express Tutorial Part 5: Displaying library information
  • Express Tutorial Part half dozen: Working with forms
  • Express Tutorial Office seven: Deploying to production

mageestrats.blogspot.com

Source: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose

0 Response to "Develop a Function to Read a Document in the Mongodb Database"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel