I want to use mongodb with sails but without any ORM. So below is my service to connect mongodb.
Service:
//DbService.js
const MongoClient = require('mongodb').MongoClient;
module.exports = {
db:function(req, res){
var connect=MongoClient.connect("mongodb:***********").then(function (err, database) {
if(err) console.log(err);
else{
database=database.db('*****');
return connect;
}
});
}
}
After connection i have called it in controller, But getting TypeError: Cannot read property 'then' of undefined.
controller:
//HomeControlelr.js
module.exports = {
index:function(req, res){
DbService.db().then(function(err,db) {
console.log(db);
})
}
};
First npm i mongodb
because you'll need to wrap any ID's with new ObjectID(idStr)
.
Then you can do this:
const collection = Pet.getDatastore().manager.collection(Pet.tableName);
const res = await collection.find({ name: { $regex: /blue/ } });
const dataWithObjectIds = await res.toArray();
const dataWithIds = JSON.parse(JSON.stringify(rawDataArr).replace(/"_id"/g, '"id"'));
I created a helper function to do all of this for us:
/**
* Use by chaining as if you were acting on a collection. So can use .find .aggregate etc.
* Returns json searializable data.
*
* @param {class} model A model
* @param {number} cnt - Number of chains on this, so I know when it reached the end
*/
function nativeMongoQuery(model, cnt) {
const collection = model.getDatastore().manager.collection(model.tableName);
let callCnt = 0;
let req;
const proxy = new Proxy({}, {
get: (_, method) => (...args) => {
if (!req) req = collection[method](...args);
else req = req[method](...args);
callCnt++;
if (callCnt === cnt) {
return (async function() {
const rawDataArr = await req.toArray();
return JSON.parse(JSON.stringify(rawDataArr).replace(/"_id"/g, '"id"'));
})();
} else {
return proxy;
}
}
});
return proxy;
}
module.exports = nativeMongoQuery;
I don't like the JSON parse and stringify and global replace. But if I don't do the stringify, then mongo _id's are all ObjectId
s.
Use it like this:
const { ObjectId } = require('mongodb');
function makeObjectId(id) {
return new ObjectId(id);
}
const ownerIds = ['5349b4ddd2781d08c09890f4', '5349b4ddd2781d08c09890f5']
const ownerObjectIds = ownerIds.map(makeObjectId);
await nativeMongoQuery(Pet, 2).find({ owner: { $in: ownerObjectIds } }).sort({ dueAt: 1 });
Here is another example:
const mostRecentlyCreatedPets = await nativeMongoQuery(Pet, 1).aggregate([
{ $match: { owner: { $in: ownerObjectIds } } },
{ $sort: { createdAt: -1 } },
{ $limit: 1 }
]);
The cnt
argument tells you how many things you have chained off of there.
As you can see in docs MongoClient.connect()
doesn't return Promise object. Instead of this use callback function
module.exports = {
db:function(){
var connect = MongoClient.connect("mongodb:***********", function (err, database) {
//...
}
});
}
}
btw. Your call DbService.db
function in controller will also fail, cuz your service function also doesn't return Promise
Before you go on, read something about Promises and callback functions