With the Release of MongoDB 3.4, creation of read-only views are supported from existing collections or views.

Read-Only Views are same as MongoDB collections, but is used only to read from, as they don't contains the actual documents, instead they act like a mirror collections, and hence no space is consumed when creating a views, except for the definition of the view, stored in system.views collection , and any changes in the original collection are reflected back in the view automatically on the fly.

Views can be created by using simple filter query to advanced aggregation pipeline, when querying the view it will use the indexes from original collection if available,

Creating and Dropping views:

To throughly understand how views in MongoDB works, the best way is to see it in action.
In this hands-on, we will use the examples used by MongoDB University for course M034: New Features and Tools in MongoDB 3.4
Consider personnel database with employees collection containing below documents

[
  {
		name: "Will Cross",
		team: "Curriculum",
		likes: ["physics", "lunch", "mongodb"]
	},
	{
		name: "Zach Davis",
		team: "Curriculum",
		likes: ["video games", "windows", "lunch", "mongodb"]
	},
	{
		name: "Kirby Kohlmorgen",
		team: "Curriculum",
		likes: ["mongodb", "New York", "lunch"]
	},
	{
		name: "Graham Lowe",
		team: "University Platform",
		likes: ["mongodb", "Tim Horton's", "leadership"]
	},
	{
		name: "John Yu",
		team: "University Platform",
		likes: ["video games", "lunch", "mongodb", "rubik's cube"]
	},
	{
		name: "David Percy",
		team: "University Platform",
		likes: ["mongodb", "lunch", "video games", "puzzles"]
	},
	{
		name: "Jason Flax",
		team: "University Platform",
		likes: ["mongodb", "lunch", "current events", "design"]
	}
]

we will create a view, which will only contain name & team fields, and for that we will use below command:

db.createView( "justNameAndTeam", "employees", [
    { $project: { _id: 0, name: 1, team : 1 } } ] );

To create view you pass the view name, collection name, pipeline and optionally collation.

If view was successfully created, you will see below output.

{ "ok" : 1 }

If you receive below error in MongoDB Shell

{
	"ok" : 0,
	"errmsg" : "Cannot create view when the featureCompatibilityVersion is 3.2. See http://dochub.mongodb.org/core/3.4-feature-compatibility.",
	"code" : 115,
	"codeName" : "CommandNotSupported"
}

Run below commands on MongoDB shell

use admin;
db.adminCommand( { setFeatureCompatibilityVersion: "3.4" } );
use personnel;
db.createView( "justNameAndTeam", "employees", [
    { $project: { _id: 0, name: 1, team : 1 } } ] );

more on this can be checked at release notes page 3.4-upgrade-standalone
One major benefit of creating view is you can restrict access to Users & Roles, for who can access what fields of documents from the collection.

Check if view was created

Run the below command on MongoDB shell

db.system.views.find()

you should see below output

{ "_id" : "personnel.justNameAndTeam", "viewOn" : "employees", "pipeline" : [ { "$project" : { "_id" : 0, "name" : 1, "team" : 1 } } ] }

thats the only information stored by MongoDB when you create view.

We query the view same as we query the normal collection, i.e.,

db.justNameAndTeam.find()

you will see below output

{ "name" : "Will Cross", "team" : "Curriculum" }
{ "name" : "Zach Davis", "team" : "Curriculum" }
{ "name" : "Kirby Kohlmorgen", "team" : "Curriculum" }
{ "name" : "Graham Lowe", "team" : "University Platform" }
{ "name" : "John Yu", "team" : "University Platform" }
{ "name" : "David Percy", "team" : "University Platform" }
{ "name" : "Jason Flax", "team" : "University Platform" }

Notice that the view justNameAndTeam only returns the name and team fields that we specified while creating view, just to remind, you can create a User with Read-only access to justNameAndTeam, so that the user can only view limited field.

Complex view

You can also create more complex views, i.e., below command creates a view, to find what is most liked by Curriculum team.

db.createView( "whatCurriculumLikes", "employees", [
        { $match : { team : "Curriculum" } },
        { $unwind : "$likes" }, 
        { 
            $group : 
            { 
                _id : { topic : "$likes" },
                popularity : { $sum : 1 } 
            } 
        }, {
            $sort : { popularity: -1 }
        } ] );

and when queried would return below documents

db.whatCurriculumLikes.find()
{ "_id" : { "topic" : "lunch" }, "popularity" : 3 }
{ "_id" : { "topic" : "mongodb" }, "popularity" : 3 }
{ "_id" : { "topic" : "physics" }, "popularity" : 1 }
{ "_id" : { "topic" : "New York" }, "popularity" : 1 }
{ "_id" : { "topic" : "windows" }, "popularity" : 1 }
{ "_id" : { "topic" : "video games" }, "popularity" : 1 }

you can see from the above output that, as pipeline written in the above view, documents are first filtered with topic Curriculum, sum of likes are calculated by grouping, and finally sorted DESC by sum of likes.

Indexes, Views, and Performance

Creating indexes on View are not supported, and every time you query the view, the operation is performed on original collection, and nothing is cached, if indexes are created on original collections, those are utilized when querying, to check if indexes are utilized or if your view is using efficient scanning technique, do run the explain command on your view, i.e., below command will output the execution plan for your views, the way it does for collection queries.

db.whatCurriculumLikes.explain("executionStats").find()

So when writing pipeline for views you should utilize the available indexes on source collection and do $match to filter the documents.

Operations not supported by views

  1. You can not use $natural sort on a view.
  2. You can't perform below projection operation on view.
  3. You can not rename view, as they are immutable.
  4. You can not use MapReduce on view, as results are computed on the fly, as a part of underlying aggregation pipeline.
  5. You can not use $text operator, as in aggregation, its valid only for first stage.
  6. geoNear command and $geoNear pipeline stage, are not supported.

If you enjoyed reading the post, please subscribe by filling your email address below to receive latest updates, and don't forget to share this post on your social network.

Thanks!