Note
Disambiguation
This page discusses on-demand materialized views. For discussion of standard views, see Views.
To understand the differences between the view types, see Comparison with Standard Views.
An on-demand materialized view is a pre-computed aggregation pipeline
result that is stored on and read from disk. On-demand materialized
views are typically the results of a $merge or
$out stage.
Comparison with Standard Views
MongoDB provides two different view types: standard views and on-demand materialized views. Both view types return the results from an aggregation pipeline.
Standard views are computed when you read the view, and are not stored to disk.
On-demand materialized views are stored on and read from disk. They use a
$mergeor$outstage to update the saved data.Note
When using
$merge, you can use change streams to watch for changes on the materialized view. When using$out, you can't watch for changes on the materialized view.
Indexes
Standard views use the indexes of the underlying collection. As a result, you cannot create, drop or re-build general indexes on a standard view directly, nor get a list of general indexes on the view.
MongoDB stores search indexes and vector search indexes on disk. Accordingly, you can create MongoDB Search indexes and MongoDB Vector Search indexes on compatible views that contain only the following stages:
You can also create indexes directly on on-demand materialized views because MongoDB stores those indexes on disk.
Performance
On-demand materialized views provide better read performance than standard views because they are read from disk instead of computed as part of the query. This performance benefit increases based on the complexity of the pipeline and size of the data being aggregated.
Create a Materialized View in the MongoDB Atlas UI
The example in this section uses the sample training dataset. To learn how to load the sample dataset into your MongoDB Atlas deployment, see Load Sample Data.
To create a materialized view in the MongoDB Atlas UI, follow these steps:
In the MongoDB Atlas UI, go to the Clusters page for your project.
If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.
If it's not already displayed, select your project from the Projects menu in the navigation bar.
In the sidebar, click Clusters under the Database heading.
The Clusters page displays.
Select an aggregation stage from the Select drop-down menu
The aggregation stage transforms the data that you want to save as a view. To learn more about available aggregation stages, see Aggregation Stages.
For this example, add a new field with the $set stage:
Select
$setfrom the Select drop-down menu.Add the following syntax to the aggregation pipeline editor to create an average score across all
scorevalues in thescoresarray within thegradescollection:{ averageScore: { $avg: "$scores.score" } } MongoDB Atlas adds the
averageScorevalue to each document.
Add the $out stage
Select the
$outstage from the Select drop-down menu.Add the following syntax to the aggregation pipeline to write the results of the pipeline to the
myViewcollection in thesample_trainingdatabase:'myView' Click Save Documents.
The $out stage writes the results of the
aggregation pipeline to the specified collection, which creates
the view. To learn more, see $out.
Refresh the list of collections to see the myView collection.
To learn how to query the myView collection in the MongoDB Atlas
UI, see View, Filter, and Sort Documents in the
MongoDB Atlas documentation.
Example
The example uses the movies collection from the
sample_mflix dataset.
To learn how to load sample data, see
Load Sample Data.
1. Define the On-Demand Materialized View
The following updateMovieStats function defines a
movieYearStats materialized view that contains the
count and average IMDb rating of movies by year. The function
accepts a startYear parameter to update statistics for
movies released from that year forward.
updateMovieStats = function(startYear) { db.movies.aggregate( [ { $match: { year: { $gte: startYear } } }, { $group: { _id: "$year", movieCount: { $sum: 1 }, avgRating: { $avg: "$imdb.rating" } } }, { $merge: { into: "movieYearStats", whenMatched: "replace" } } ] ); };
The
$matchstage filters movies to process only those with ayearvalue greater than or equal tostartYear.The
$groupstage groups movies byyear. The documents output by this stage have the form:{ "_id" : <year>, "movieCount" : <num>, "avgRating" : <num> } The
$mergestage writes the output to themovieYearStatscollection.The stage matches on the
_idfield and checks if each aggregation result matches an existing document:When there is a match (that is, a document with the same year already exists in the collection), the stage replaces the existing document with the document from the aggregation results.
When there isn't a match, the stage inserts the document from the aggregation results into the collection (the default behavior when not matched).
2. Perform Initial Run
For the initial run, pass in a starting year to populate
movieYearStats with data from that year forward:
updateMovieStats(2015);
After the initial run,
db.movieYearStats.find().sort( { _id: 1 } ) returns
documents like the following:
{ "_id" : 2015, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2016, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2017, "movieCount" : <num>, "avgRating" : <num> }
3. Refresh Materialized View
Assume a new movie is added to the movies collection
for 2016:
db.movies.insertOne( { title: "Grove Test Movie", year: 2016, imdb: { rating: 7.5, votes: 500 } } )
To refresh movieYearStats for 2016 onward, run the
function with a startYear of 2016:
updateMovieStats(2016);
The updated movieYearStats reflects the new movie in the
movies collection.
db.movieYearStats.find().sort( { _id: 1 } ) returns:
{ "_id" : 2015, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2016, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2017, "movieCount" : <num>, "avgRating" : <num> }
Additional Information
The $merge stage:
Can output to a collection in the same or different database.
Creates a new collection if the output collection does not already exist.
Can incorporate results (insert new documents, merge documents, replace documents, keep existing documents, fail the operation, process documents with a custom update pipeline) into an existing collection.
Can output to a sharded collection. Input collection can also be sharded.
See $merge for:
More information on
$mergeand available optionsExample: Only Insert New Data