MongoDB is the leading NoSQL database, with significant adoption among the Fortune 500 and Global 500. Check that complete list of 35 advanced MongoDB interview questions and answers and nail your NoSQL developer interview!
A NoSQL database provides a mechanism for storage and retrieval of data that is modeled in means other than the tabular relations used in relational databases (like SQL, Oracle, etc.).
Types of NoSQL databases:
MongoDB is an open-source document database that provides high performance, high availability, and automatic scaling.
Its Key Features are:
Replication is the process of synchronizing data across multiple servers.
Replication provides redundancy and increases data availability. With multiple copies of data on different database servers, replication provides a level of fault tolerance against the loss of a single database server.
In some cases, replication can provide increased read capacity as clients can send read operations to different servers. Maintaining copies of data in different data centres can increase data locality and availability for distributed applications. You can also maintain additional copies for dedicated purposes, such as disaster recovery, reporting, or backup.
Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, i.e. scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect.
Sharding is a method for distributing data across multiple machines. MongoDB uses sharding to support deployments with very large data sets and high throughput operations. MongoDB supports horizontal scaling through sharding. MongoDB shards data at the collection level, distributing the collection data across the shards in the cluster.
Yes. An array field can be indexed in MongoDB. In this case, MongoDB would index each value of the array so you can query for individual items:
> db.col1.save({'colors': ['red','blue']})
> db.col1.ensureIndex({'colors':1})
> db.col1.find({'colors': 'red'})
{ "_id" : ObjectId("4ccc78f97cf9bdc2a2e54ee9"), "colors" : [ "red", "blue" ] }
> db.col1.find({'colors': 'blue'})
{ "_id" : ObjectId("4ccc78f97cf9bdc2a2e54ee9"), "colors" : [ "red", "blue" ] }Yes.
ACID stands that any update is:
MongoDB is ACID-compilant at the document level. MongoDB added support for multi-document ACID transactions in version 4.0 in 2018 and extended that support for distributed multi-document ACID transactions in version 4.2 in 2019.
MongoDB's document model allows related data to be stored together in a single document. The document model, combined with atomic document updates, obviates the need for transactions in a majority of use cases. Nonetheless, there are cases where true multi-document, multi-collection MongoDB transactions are the best choice.
MongoDB transactions work similarly to transactions in other databases. To use a transaction, start a MongoDB session through a driver. Then, use that session to execute your group of database operations. You can run any of the CRUD (create, read, update, and delete) operations across multiple documents, multiple collections, and multiple shards.
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
collection.insertOne(clientSession, docOne);
collection.insertOne(clientSession, docTwo);
clientSession.commitTransaction();
}No.
One of the great things about relational database is that it is really good at keeping the data consistent within the database. One of the ways it does that is by using foreign keys. A foreign key constraint is that let's say there's a table with some column which will have a foreign key column with values from another table's column.
In MongoDB, there's no guarantee that foreign keys will be preserved. It's upto the programmer to make sure that the data is consistent in that manner. Constraints can not be enforced by MongoDB either. It can't even enforce a specific type for a field, due to the schemaless nature of MongoDB.
ObjectID in MongoDBObjectIds are small, likely unique, fast to generate, and ordered. ObjectId values consist of 12 bytes, where the first four bytes are a timestamp that reflect the ObjectId’s creation. Specifically:
db.CollectionName.find({"whenCreated": {
'$gte': ISODate("2018-03-06T13:10:40.294Z"),
'$lt': ISODate("2018-05-06T13:10:40.294Z")
}});By default MongoDB does not support such primary key - foreign key relationships. However, we can achieve this concept by embedding one document inside another (aka subdocuments).
Embedded data models allow applications to store related pieces of information in the same database record. As a result, applications may need to issue fewer queries and updates to complete common operations.
In general, use embedded data models when:
JOIN equivalent in MongoDB?Mongo is not a relational database, and the devs are being careful to recommend specific use cases for $lookup, but at least as of 3.2 doing join is now possible with MongoDB. The new $lookup operator added to the aggregation pipeline is essentially identical to a left outer join:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}Data in MongoDB is stored in BSON documents – JSON-style data structures. Documents contain one or more fields, and each field contains a value of a specific data type, including arrays, binary data and sub-documents. Documents that tend to share a similar structure are organized as collections. It may be helpful to think of documents as analogous to rows in a relational database, fields as similar to columns, and collections as similar to tables.
The advantages of using documents are:
%like%?I want to query something as SQL's like query:
select *
from users
where name like '%m%'How to do the same in MongoDB?
db.users.find({name: /a/}) //like '%a%'
db.users.find({name: /^pa/}) //like 'pa%'
db.users.find({name: /ro$/}) //like '%ro'Or using Mongoose:
db.users.find({'name': {'$regex': 'sometext'}})SELECT * FROM collection WHERE _id IN (1,2,3,4)?Consider:
db.collection.find({ _id: { $in: [1, 2, 3, 4] } });It depends from your goals. Normalization will provide an update efficient data representation. Denormalization will make data reading efficient.
In general, use embedded data models (denormalization) when:
In general, use normalized data models:
Also normalizing your data like you would with a relational database is usually not a good idea in MongoDB. Normalization in relational databases is only feasible under the premise that JOINs between tables are relatively cheap. The $lookup aggregation operator provides some limited JOIN functionality, but it doesn't work with sharded collections. So joins often need to be emulated by the application through multiple subsequent database queries, which is very slow (see question MongoDB and JOINs for more information).
The shard key is either a single indexed field or multiple fields covered by a compound index that determines the distribution of the collection's documents among the cluster's shards.
MongoDB divides the span of shard key values (or hashed shard key values) into non-overlapping ranges of shard key values (or hashed shard key values). Each range is associated with a chunk, and MongoDB attempts to distribute chunks evenly among the shards in the cluster.
The shard key has a direct relationship to the effectiveness of chunk distribution.
What do we need to really know as a developer?
insert must include a shard key, so if it's a multi-parted shard key, we must include the entire shard keyupdate, remove, find - if mongos is not given a shard key - then it's going to have to broadcast the request to all the different shards that cover the collection.update - if we don't specify the entire shard key, we have to make it a multi update so that it knows that it needs to broadcast itTTL collections make it possible to store data in MongoDB and have the mongod automatically remove data after a specified number of seconds or at a specific clock time.
For example, the following operation creates an index on the log_events collection's createdAt field and specifies the expireAfterSeconds value of 10 to set the expiration time to be ten seconds after the time specified by createdAt.
db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 10 } )When adding documents to the log_events collection, set the createdAt field to the current time:
db.log_events.insertOne( {
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "Success!"
} )MongoDB will automatically delete documents from the log_events collection when the document's createdAt value [1] is older than the number of seconds specified in expireAfterSeconds.
To expire documents at a specific clock time, begin by creating a TTL index on a field that holds values of BSON date type or an array of BSON date-typed objects and specify an expireAfterSeconds value of 0.
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )For each document, set the value of expireAt to correspond to the time the document should expire. For example, the following insertOne() operation adds a document that expires at July 22, 2013 14:00:00.
db.log_events.insertOne( {
"expireAt": new Date('July 22, 2013 14:00:00'),
"logEvent": 2,
"logMessage": "Success!"
} )MongoDB will automatically delete documents from the log_events collection when the documents' expireAt value is older than the number of seconds specified in expireAfterSeconds, i.e. 0 seconds older in this case. As such, the data expires at the specified expireAt value.
Aggregation operations process multiple documents and return computed results. You can use aggregation operations to:
MongoDB provides aggregation operations through aggregation pipelines — a series of operations that process data documents sequentially. An aggregation pipeline consists of one or more stages that process documents:
Consider:
db.orders.aggregate([
// Stage 1: Filter pizza order documents by pizza size
{
$match: { size: "medium" }
},
// Stage 2: Group remaining documents by pizza name and calculate total quantity
{
$group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
}
])Consider the SQL query:
SELECT by, SUM(price) AS total FROM book GROUP BY price ORDER BY totalWrite down the MongoDB equivalent.
Consider:
db.book.aggregate([
{
$group: {
_id: "$by",
total: { $sum:"$price" }
}
},
{
$sort: { total:1 }
}
])sex first or name first? Explain.Rust has been Stack Overflow’s most loved language for four years in a row and emerged as a compelling language choice for both backend and system developers, offering a unique combination of memory safety, performance, concurrency without Data races...
Clean Architecture provides a clear and modular structure for building software systems, separating business rules from implementation details. It promotes maintainability by allowing for easier updates and changes to specific components without affe...
Azure Service Bus is a crucial component for Azure cloud developers as it provides reliable and scalable messaging capabilities. It enables decoupled communication between different components of a distributed system, promoting flexibility and resili...