To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.
In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.
Queries
Mongoose comes with various query methods.
We can use the findOne
method to return the first entry that matches the query.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: {
first: String,
last: String
},
occupation: String
});
const Person = connection.model('Person', schema);
const person = new Person({
name: {
first: 'james',
last: 'smith'
},
occupation: 'waiter'
})
await person.save();
const p = await Person.findOne({ 'name.last': 'smith' }, 'name occupation');
console.log(p);
}
run();
We create the Person
schema and save a document that’s created from the Person
constructor.
Then we call findOne
to find an entry.
The first argument is an object with the query. 'name.last'
is the path to the nested field.
The 2nd argument is a string with the columns that we want to select.
Then we can get the result from the thenable object.
Even though we can use async
and await
, with the findOne
method, it doesn’t return a promise.
Then then
method is provided so that we can use the async
and await
syntax.
We should not mix promises and callbacks.
For example, we shouldn’t write code like:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: {
first: String,
last: String
},
occupation: String
});
const Person = connection.model('Person', schema);
const person = new Person({
name: {
first: 'james',
last: 'smith'
},
occupation: 'waiter'
})
await person.save();
const update = { name: { first: ['alex'] } };
const p = await Person.updateOne({ 'name.first': 'james' }, update, (err, res) => {
console.log(res);
});
console.log(p)
}
run();
Streaming
We can stream query results from MongoDB.
To do that, we call the cursor
method:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: {
first: String,
last: String
},
occupation: String
});
const Person = connection.model('Person', schema);
const person = new Person({
name: {
first: 'james',
last: 'smith'
},
occupation: 'host'
})
await person.save();
const person2 = new Person({
name: {
first: 'jane',
last: 'smith'
},
occupation: 'host'
})
await person2.save();
const cursor = Person.find({ occupation: /host/ }).cursor();
let doc;
while (doc = await cursor.next()) {
console.log(doc);
}
}
run();
We created 2 Person
documents.
Then we call find
with the query to return the ones with the occupation
field that matches the /host/
regex pattern.
Then we use the while
loop to get the cursor.next()
method to get the next item from the cursor object.
We can also use the for-await-of
loop to do the same thing:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: {
first: String,
last: String
},
occupation: String
});
const Person = connection.model('Person', schema);
const person = new Person({
name: {
first: 'james',
last: 'smith'
},
occupation: 'host'
})
await person.save();
const person2 = new Person({
name: {
first: 'jane',
last: 'smith'
},
occupation: 'host'
})
await person2.save();
const query = Person.find({ occupation: /host/ });
for await (const doc of query) {
console.log(doc);
}
}
run();
We don’t need the cursor
method anymore since find
and other query methods return the cursor when we use it with for-await-of
.
Conclusion
We can make queries with Mongoose to get data.