DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Java and MongoDB Integration: A CRUD Tutorial [Video Tutorial]
  • MongoDB to Couchbase for Developers, Part 1: Architecture
  • MongoDB to Couchbase: An Introduction to Developers and Experts
  • Manage Hierarchical Data in MongoDB With Spring

Trending

  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  • Integration Isn’t a Task — It’s an Architectural Discipline
  • A Complete Guide to Modern AI Developer Tools
  • Automating Data Pipelines: Generating PySpark and SQL Jobs With LLMs in Cloudera
  1. DZone
  2. Data Engineering
  3. Databases
  4. Taking a Look at MongoDB Views

Taking a Look at MongoDB Views

MongoDB's views are a recent innovation that help with both data security and abstraction. They don't use disk space or a physical schema, so see how they work!

By 
Adamo Tonete user avatar
Adamo Tonete
·
Jan. 20, 17 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
37.8K Views

Join the DZone community and get the full member experience.

Join For Free

MongoDB 3.4 ViewsThis blog post covers MongoDB 3.4 views, one of the more recent MongoDB features.

Views are often used in relational databases to achieve both data security and a high level of abstraction, making it easier to retrieve data. Unlike regular tables, views neither have a physical schema nor use disk space. They execute a pre-specified query. There are exceptions (such as materialized views and pre-executed views), but as a default the engine actually executes a query and then sends the result set as a single table when a view is used.

In MySQL, a simple view can be defined as:

create database percona;
 
use percona;
 
create view user_hosts as select user, host from mysql.user;
 
select * from user_hosts 
 
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| myuser           | %         |
 
...


The query above shows only the users and host field, rather than all the table fields. Anyone who queries this view sees a table that only has the user and host fields.

This feature was not available in previous MongoDB versions. All we could do was either deny reads in a collection (which would make it useless to the user) or allow reads to the entire collection (which was pretty unsafe).

The views feature request was open for a while, and as we can see there was a considerable number of votes to make this feature available: https://jira.mongodb.org/browse/SERVER-142.

MongoDB 3.4 views are non-materialized views, and behind the scenes the engine runs an aggregation. Creating a view requires that we specify a collection or a previous existing view. When a view is the source collection from another view, it allows us to execute a chained aggregation.

To create a view, we should use the db.createView(‘view_name’,’source’,[pipeline]) command, specifying the view name, the view source collection and the aggregation pipeline. This aggregation pipeline, as well as the other parameters, is saved in the system.views collection. This is the only space that the view will use in the system. A new document is saved in the system.views collection for each view created.

Although views seem very easy to create, a few pitfalls when using them.

Since views always run an aggregation, an index is desired to cover the aggregation $match pipeline, or slow responses might be expected during the full collection scans.

Cascading aggregations (creating views of views) can be slow, as the view does not have any data and therefore cannot be indexed. MongoDB neither checks the collection fields nor the collection existence before creating the view. If there is no collection, the view returns an empty cursor.

Views appear as a collection when we are listing them. The show collections command shows us views as one collection, but such collections are read-only. To drop a view, we simply execute db.collection.drop(). The collection is removed from the system.collections, but the data remains untouched because it only removes the code that generates the view result.

How to Create Views

In this step-by-step, we will create a view and restrict the user UserReadOnly to read privileges only:

1. Populate a collection:

$ mongo --authenticatinDatabase admin -u foo -p
use financial
switched to db financial
> db.employee.insert({FirstName : 'John', LastName:  'Test', position : 'CFO', wage : 180000.00 })
WriteResult({ "nInserted" : 1 })
> db.employee.insert({FirstName : 'John', LastName:  'Another Test', position : 'CTO', wage : 210000.00 })
WriteResult({ "nInserted" : 1 })
> db.employee.insert({FirstName : 'Johnny', LastName:  'Test', position : 'COO', wage : 180000.00 })
WriteResult({ "nInserted" : 1 })


2. Create a view that only shows full names:

use financial
db.createView('employee_names','employee', [{ $project : { _id : 0, "fullname" : {$concat : ["$FirstName", " ", "$LastName"]}}}])
{ "ok" : 1 }
>show collections
employee
employee_names
system.views
db.system.views.find()
db.employee_names.find()
{ "fullname" : "John Test" }
{ "fullname" : "John Another Test" }
{ "fullname" : "Johnny Test" }


3. Create a user-defined role that only gives access to the views:

Create a file “createviewOnlyRole.js” with the following javascript, or copy and paste the following code: 

use financial
db_name = db.toString()
priv = []
db.system.views.find({},{"_id" : 1, "viewOn" : 1}).forEach(function (view) {
    database_collection = view['_id'].split('.')
    database = database_collection[0]
    database_collection.splice(0,1)
    coll = database_collection.join([separator = '.'])
    priv.push({"resource" : { "db" : database, "collection" : coll}, "actions" : ["find"]})
})
var viewrole = db.getRole(db_name + '_readAnyView')
if (viewrole == null) {
     db.runCommand({ createRole: db_name + "_readAnyView",
    "privileges": priv,
    roles : []
    });
} else {
	db.runCommand({ updateRole: db_name + "_readAnyView",
    "privileges": priv,
    roles : []
    });
}
print('access granted to:')
printjson(priv)


Then authenticate and use the desired database to create this role. In our case:

use financial
db.load('createviewOnlyRole.js')


4. Create a new user assigned to the readAnyView role. This new user is only able to query against views, and they must know the view name because no other privileges are granted:

use financial
db_name = db.toString()
db.createUser(
   {
     user: "userReadViews",
     pwd: "123",
     roles: [ db_name + "_readAnyView"]
   }
)


Note: If you receive an error when trying to execute the .js file, please create a new role that grants find in the system.views collection:

use admin
db.runCommand({ createRole: "readViewCollection",
  privileges: [
    { resource: { db: "", collection: "system.views" }, actions: [ "find"] }],
    roles : []
})
db.grantRoleToUser('<your_user>',['readViewCollection'])


For more information about user-defined roles, please check please check the user-defined docs.

This should help explain MongoDB 3.4 views. Please feel free to contact me @AdamoTonete or @percona for any questions and suggestions.

MongoDB Database Relational database

Published at DZone with permission of Adamo Tonete, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Java and MongoDB Integration: A CRUD Tutorial [Video Tutorial]
  • MongoDB to Couchbase for Developers, Part 1: Architecture
  • MongoDB to Couchbase: An Introduction to Developers and Experts
  • Manage Hierarchical Data in MongoDB With Spring

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!