In today’s data-driven ecosystem, organizations face a significant challenge: balancing the imperative for data accessibility with stringent security requirements. Data access and sharing data across teams or third parties are a very common phenomenon. One of the most common scenarios database administrators and architects encounter is the need to share collection data with various stakeholders—internal teams, partners, or third-party services—without compromising sensitive information. However, why even share data which is irrelevant for the data consumer. Suppose a MongoDB collection contain sensitive information. To restrict the access to collection, MongoDB offers Role-Based Access Control (RBAC).

mongodb views

While MongoDB’s Role-Based Access Control (RBAC) provides a foundation for securing collections at a broad level, it often creates a binary scenario—either full access or no access. However, there may be instances where you want to share your collection with a broader audience without exposing sensitive data or irrelevant information. For example, sharing collections with the marketing team for analytics purposes without divulging personally identifiable information (PII) or confidential data like credit card number etc.

MongoDB views emerge as a sophisticated solution to this challenge, enabling organizations to implement granular access control while maintaining a single source of truth. This article explores how MongoDB views, when combined with RBAC, provide a powerful architecture for secure data sharing in enterprise environments.

Understanding Data Security Challenges

Before diving into the technical implementation, it’s essential to understand the data security challenges organizations face:

1. Regulatory Compliance: With regulations like GDPR, CCPA, HIPAA, and PCI-DSS imposing strict requirements on data handling, organizations must implement mechanisms to limit exposure of sensitive information.

2. Need-to-Know Basis: Different teams require different subsets of data. For example, marketing teams may need demographic information without access to financial details, while customer service may need contact information without seeing internal notes.

3. Data Integrity: Ensuring that stakeholders cannot modify data they should only view is crucial for maintaining data integrity.

4. Performance Considerations: Security implementations should not significantly impact query performance or introduce unacceptable latency.

5. Operational Complexity: Security solutions must be maintainable and not introduce excessive operational overhead.

MongoDB views address these challenges by creating virtual collections that present filtered or transformed versions of underlying data.

Prerequisites for Implementing MongoDB Views

To successfully implement the security architecture described in this article, you’ll need:

  • A MongoDB deployment (version 3.4 or newer) with authentication enabled
  • Administrative access or a user with permissions to:
    • Create and manage views
    • Configure RBAC roles and privileges
    • Create users and assign roles
  • Basic familiarity with MongoDB query operations and aggregation framework

Assuming you already have an admin user on your cluster with full privileges or at least a user with permissions to create views, custom roles, and users.

Database Schema and Sample Data

Let’s examine a scenario involving a persons collection containing sensitive customer information. This collection might be used by various departments within an organization but contains fields that should be restricted based on the department’s requirements.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
db.persons.insertMany([
    {
        _id: 100,
        first_name: 'John',
        last_name: 'Dave',
        age: 21,
        sex: 'M',
        credit_card_number: '4541-3510-0040-7153',
        date_of_expiry: '31-Dec-2023',
        email_id: 'dave.john@gmail.com',
        annual_income: 75000,
        purchase_history: [
            { date: '2023-01-15', amount: 1299.99, item: 'Laptop' },
            { date: '2023-03-22', amount: 699.99, item: 'Smartphone' }
        ],
        address: {
            street: '123 Main St',
            city: 'Boston',
            state: 'MA',
            zip: '02108'
        },
        account_creation_date: '2022-08-10'
    },
    {
        _id: 101,
        first_name: 'Anna',
        last_name: 'Smith',
        age: 23,
        sex: 'F',
        credit_card_number: '4541-7802-0568-8842',
        date_of_expiry: '25-Nov-2023',
        email_id: 'smith.anna@gmail.com',
        annual_income: 82000,
        purchase_history: [
            { date: '2023-02-03', amount: 499.99, item: 'Tablet' },
            { date: '2023-04-17', amount: 129.99, item: 'Headphones' }
        ],
        address: {
            street: '456 Oak Ave',
            city: 'Chicago',
            state: 'IL',
            zip: '60601'
        },
        account_creation_date: '2022-06-22'
    },
    // ... more records ...
]);

This collection contains several categories of sensitive information:

  • Personal Identifiable Information (PII): Names, age, gender, email, and address
  • Financial Information: Credit card details, expiration dates, income
  • Behavioral Data: Purchase history
  • Account Information: Creation dates and identifiers

Different departments within the organization have valid needs to access portions of this data:

  • Customer Retention Team: Needs to send reminders about expiring credit cards but shouldn’t see the full card numbers, income, or detailed purchase history
  • Marketing Analytics: Requires demographic information and purchase patterns but not contact details or financial information
  • Product Development: Needs anonymized purchase data without any personally identifiable information

With MongoDB RBAC, we can restrict data access to ‘Persons’ collection. However, what if we want to share this data with the customer retention team so that they can contact the persons whose credit card is going to expire soon and send reminders about renewal. For this use case, age and sex seems irrelevant and credit card number is a sensitive data and should not be shared. The retention team only needs to know about basic information like name, date of expiry and contact details.

Implementing MongoDB Views for Secure Access

As disscussed above, we want to share ‘Persons’ collection with a wider audience with selective information only. We can create a view that only includes selected fields. Here’s an example of creating a view named “reminder_view” using the $project stage:

View 1: Credit Card Expiration Reminders

First, let’s create a view for the customer retention team that includes only the necessary fields for sending reminders about expiring credit cards:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
db.createView(
    'reminder_view', 
    'persons', 
    [
        {
            $project: {
                first_name: 1, 
                last_name: 1, 
                date_of_expiry: 1, 
                email_id: 1,
                masked_card: {
                    $concat: [
                        "XXXX-XXXX-XXXX-", 
                        { $substr: ["$credit_card_number", 15, 4] }
                    ]
                }
            }
        }
    ]
);

This view not only limits the fields visible to the retention team but also transforms the credit card number to show only the last four digits, enhancing security while preserving necessary functionality.

Querying this view would yield:

1
db.reminder_view.find();

The result will show the documents with the selected fields only, excluding the sensitive and irrelevant ones.

Result

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[
  { 
    _id: 100, 
    first_name: 'John', 
    last_name: 'Dave', 
    date_of_expiry: '31-Dec-2023', 
    email_id: 'dave.john@gmail.com',
    masked_card: 'XXXX-XXXX-XXXX-7153' 
  },
  { 
    _id: 101, 
    first_name: 'Anna', 
    last_name: 'Smith', 
    date_of_expiry: '25-Nov-2023', 
    email_id: 'smith.anna@gmail.com',
    masked_card: 'XXXX-XXXX-XXXX-8842' 
  }
]

View 2: Marketing Analytics

For the marketing team, we want to provide demographic information and purchase patterns without exposing personal contact details:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
db.createView(
    'marketing_analytics_view', 
    'persons', 
    [
        {
            $project: {
                age: 1, 
                sex: 1,
                annual_income: 1,
                purchase_history: 1,
                account_age_months: {
                    $round: [
                        {
                            $divide: [
                                { $subtract: [new Date(), { $dateFromString: { dateString: "$account_creation_date" } }] },
                                (1000 * 60 * 60 * 24 * 30)  // Approximate months
                            ]
                        },
                        0
                    ]
                },
                state: "$address.state",
                city: "$address.city"
            }
        },
        {
            $addFields: {
                purchase_total: { $sum: "$purchase_history.amount" },
                purchase_count: { $size: "$purchase_history" }
            }
        }
    ]
);

This view provides rich data for marketing analysis while completely eliminating PII and financial information. It also adds computed fields like account age and purchase statistics that are immediately useful for analytics.

View 3: Anonymized Data for Product Development

For product development teams, we want to provide completely anonymized purchase data:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
db.createView(
    'product_analytics_view', 
    'persons', 
    [
        {
            $project: {
                _id: 0,
                customer_segment: {
                    $concat: [
                        { $substr: ["$sex", 0, 1] },
                        "-",
                        { 
                            $switch: {
                                branches: [
                                    { case: { $lte: ["$age", 25] }, then: "18-25" },
                                    { case: { $lte: ["$age", 35] }, then: "26-35" },
                                    { case: { $lte: ["$age", 50] }, then: "36-50" }
                                ],
                                default: "51+"
                            }
                        },
                        "-",
                        "$address.state"
                    ]
                },
                purchase_history: 1
            }
        },
        { $unwind: "$purchase_history" },
        {
            $project: {
                customer_segment: 1,
                purchase_date: "$purchase_history.date",
                purchase_amount: "$purchase_history.amount",
                item_purchased: "$purchase_history.item"
            }
        }
    ]
);

This view completely anonymizes the data, replacing identifiable information with demographic segments while preserving the purchase information needed for product analysis.

Implementing Role-Based Access Control for Views

Creating views is only half the solution. We must also ensure appropriate access control through MongoDB’s RBAC system. Let’s create specific roles for each department:

Role 1: Customer Retention Team

1
2
3
4
5
6
7
8
use admin
db.createRole({
    role: "retention_team_role",
    privileges: [
        { resource: { db: "test", collection: "reminder_view" }, actions: ["find"] }
    ],
    roles: []
});

Role 2: Marketing Analytics Team

1
2
3
4
5
6
7
8
use admin
db.createRole({
    role: "marketing_analytics_role",
    privileges: [
        { resource: { db: "test", collection: "marketing_analytics_view" }, actions: ["find"] }
    ],
    roles: []
});

Role 3: Product Development Team

1
2
3
4
5
6
7
8
use admin
db.createRole({
    role: "product_development_role",
    privileges: [
        { resource: { db: "test", collection: "product_analytics_view" }, actions: ["find"] }
    ],
    roles: []
});

Next, we can create a user with the created role:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
use admin
db.createUser({
    user: 'retention_user', 
    pwd: 'securePassword123', 
    roles: ["retention_team_role"]
})

db.createUser({
    user: 'marketing_user', 
    pwd: 'securePassword456', 
    roles: ["marketing_analytics_role"]
})

db.createUser({
    user: 'product_user', 
    pwd: 'securePassword789', 
    roles: ["product_development_role"]
})

Now we can share the credentials of view_user with the customer retention team, who are effectively viewing the persons data only but only which are relevant and hiding any sensitive information.

Performance Considerations and Best Practices

While MongoDB views provide powerful data security capabilities, they come with performance considerations that should be factored into your implementation:

1. View Performance: Views execute their aggregation pipeline on each query, which may impact performance for complex transformations or large datasets. Consider these strategies:

  • Create indexes that support common queries on the underlying collection
  • Limit the complexity of transformations in the view definition
  • For frequently accessed views with complex pipelines, consider materialized views using scheduled aggregations

2. Security Best Practices:

  • Regularly audit view definitions and access patterns
  • Implement a naming convention that clearly identifies the purpose and access level of each view
  • Consider using MongoDB Atlas Data Federation for more complex security requirements
  • Implement application-level encryption for highly sensitive fields

3. Operational Considerations:

  • Document all views, their purposes, and associated roles
  • Implement a change management process for view modifications
  • Regularly test view performance under expected load conditions
  • Consider the impact of schema changes on dependent views

Limitations of MongoDB Views:**

  • Read-Only: Views are read-only and cannot be used for write operations
  • Index Limitations: Views cannot have their own indexes; they rely on indexes from the underlying collection
  • Lookup Restrictions: Views created with $lookup or $graphLookup have certain restrictions
  • No Collation Creation: You cannot specify a default collation for a view

Conclusion

MongoDB views, when combined with role-based access control, provide a powerful mechanism for implementing granular data access patterns without compromising security. By creating purpose-specific views that expose only the necessary data to each stakeholder group, organizations can maintain a single source of truth while ensuring compliance with security best practices and regulatory requirements. This approach is particularly valuable in enterprises with diverse teams requiring different aspects of the same underlying data. Through careful view design and proper role assignment, MongoDB administrators can create a secure, scalable data access infrastructure that balances security with usability.

✨ Thank you for reading this comprehensive guide to MongoDB views and secure data access. I welcome your questions and feedback in the comments section below. If you’ve implemented similar solutions or have additional insights to share, please join the discussion.