Not getting id from other collection using mongodb and node.js - node.js

I am adding products under particular userId but not getting userId from other collection.
api.js
var insertDocument = function(db, callback) {
db.collection('proInfo').insertOne( {
"Product_Name": json.Product_Name,
"Brand": json.Brand,
"Color": json.Color,
"Image": json.Image,
"Price": json.Price,
"Rating": json.Rating,
"Description": json.Description,
"Category": json.Category,
"Url": urla,
**"userId":db.collection('users').findOne()[0]._id,**
}, function(err, result) {
assert.equal(err, null);
console.log("Inserted a document into the proInfo collection.");
callback(result);
});
};
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
insertDocument(db, function() {
db.close();
});
});

You have to request the user from the datbase after inserting it.
e.g. based on your code the following should work:
var insertDocument = function(db, callback) {
// Based on your code we assume that you have only one user in the database. Otherwise you have to do a find for a specific user.
db.collection('users').findOne(function (err, user) {
if (err) { return callback(err); }
db.collection('proInfo').insertOne( {
"Product_Name": json.Product_Name,
"Brand": json.Brand,
"Color": json.Color,
"Image": json.Image,
"Price": json.Price,
"Rating": json.Rating,
"Description": json.Description,
"Category": json.Category,
"Url": urla,
"userId": user._id
}, function(err, result) {
assert.equal(err, null);
console.log("Inserted a document into the proInfo collection.");
// Below I am passing the error as a first param to your callback. You can implemented as you wish, but it is a convention to use error as a first param.
callback(err, result);
});
});
};

Related

To use Mongoose find() with sort() and limit()

I want to get part of the data and it works, But when I tried to use limit() & sort() query, it's not working.
I want five data sorted by date. And it should be only 'login bio avatar_url' data. to reduce data.
But there also no error message, so I cannot find where the error from.
[My Code]
let User = require('../lib/models/userModel');
router.get("/", function (req, res, next) {
console.log(`HOME ROUTE!`);
User.find({}).limit(5).sort({
created_at: -1
}), 'login bio avatar_url', (function (err, result) {
if (err) return handleError(err);
console.log(result);
res.render('main', {
dataarray: result,
_user: req.user
})
})
});
The structure of my data looks like this.
[DATA]
{
"_id": {
"$oid": "5ebbcc92ae44dd149c12faf3"
},
"login": "apple",
"id": 10639145,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjEwNjM5MTQ1",
"avatar_url": "https://avatars0.githubusercontent.com/u/10639145?v=4",
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Cut useless data]
"name": "Apple",
"company": null,
"blog": "https://apple.com",
"location": "Cupertino, CA",
"email": null,
"hireable": null,
"bio": null,
"public_repos": 85,
"public_gists": 0,
"followers": 0,
"following": 0,
"created_at": "2015-01-21T20:19:28Z",
"updated_at": "2020-05-01T14:38:33Z"
}
When I tried to access / path, console only shows the this log.
Solved with this code. I think it's sequence problem
let User = require('../lib/models/userModel');
router.get("/", function (req, res, next) {
console.log(`HOME ROUTE!`);
User.find({},'login bio avatar_url', {limit:5}).sort({created_at:-1}).exec(function (err, result) {
if (err) console.log(err);
console.log(result);
res.render('main', {
dataarray: result,
_user: req.user
})
})
});

How to speed up node service

I have two collections categorytypes and categories, each category type has multiple categories. When I am fetching all category details in each index of category there should be a a filed of category_type giving all details of category_type.
My code is:
exports.findAllWithParentChild = (req, res) => {
let resData = [];
Models.Category.find()
.then(data => {
var results = [];
async.each(data,function(cat,callback) {
console.log(cat.categorytype_id)
Models.CategoryType.findOne({'_id' : mongoose.Types.ObjectId(cat.categorytype_id)},function(err,catType) {
var obj = cat.toObject();
obj.category_type = catType;
results.push(obj);
callback(err);
});
},
function(err) {
if (err) throw err;
res.send({
response: true,
message: "Category deleted successfully.",
data : results
});
});
});
};
And the format I need in response:
{
"_id": "5cb78c44ede6452278d13fbe",
"title": "fhhghgf",
"description": "hgfhgf",
"slug": "hgfhgfhgf",
"categorytype_id": "5cb78ba8ede6452278d13fb6",
"user_id": "hgfhgfh",
"status": true,
"created_at": "2019-04-17T20:27:48.821Z",
"updated_at": "2019-04-17T20:27:48.821Z",
"__v": 0,
"category_type": {
"_id": "5cb78ba8ede6452278d13fb6",
"title": "asde",
"description": "asde",
"slug": "asde",
"user_id": "asde",
"status": true,
"created_at": "2019-04-17T20:25:12.863Z",
"updated_at": "2019-04-17T20:25:12.863Z",
"__v": 0
}
},
Is there any better way? Thanks for your assistance.
Change your code with below one and check the output
exports.findAllWithParentChild = (req, res) => {
Models.Category.find({}).
populate('categorytypes').
exec(function (err, data) {
if (err) return handleError(err);
console.log('Success', data);
});
};

Using two apis one with object id and another with name

I have two api calls to retrieve data from the same collection using different parameters.
The first one is by the ObjectID:
app.get('/api/employees/:id', function(req, res){
Employee.findOne({_id:req.params.id}, function(err, employee){
if(err)
res.send(err);
res.json(employee);
}); });
And the second one retrieves data by the name :
app.get('/api/employees/:name', function(req, res){
Employee.findOne({name:req.params.name}, function(err, employee){
if(err)
res.send(err);
res.json(employee);
});});
I placed both Apis in my code, but only the first one is being called. If I run my code I have something like:
{
"_id": "58b00dd47689fc2f48b9baf4",
"name": "Rohtih",
"dept": "CSE",
"area": "Banglore",
"contact": "9962938489",
"status": "System Engineer",
"salary": "30000",
"__v": 0
},
My mongo collection looks Like this:
{
"_id": "58b00dd47689fc2f48b9baf4",
"name": "Rohtih",
"dept": "CSE",
"area": "Banglore",
"contact": "9962",
"status": "System Engineer",
"salary": "30000",
"__v": 0
},
{
"_id": "58b00df07689fc2f48b9baf5",
"name": "Vaibhav",
"dept": "CSE",
"area": "Banglore",
"contact": "819",
"status": "Manager",
"salary": "300000",
"__v": 0
}
I would like to know how do I use both apis at a time? Is there a mistake in my code, please help me solving this?
As I could understand from your code, you may receive both parameters but you don't know when to use what. What I would separate in two different api calls:
First one is to find by Id:
app.get('/api/employees/findById', function(req, res){
Employee.findOne({_id:req.params.id}, function(err, employee){
if(err)
res.send(err);
res.json(employee);
}); });
Second one is to find by name:
app.get('/api/employees/findByName', function(req, res){
Employee.findOne({name:req.params.name}, function(err, employee){
if(err)
res.send(err);
res.json(employee);
});});
If you don't like any of those approaches, you can leave as it is and verify if the parameters are present, for example:
app.get('/api/employees/find', function(req, res){
let name = req.params.name;
let id = req.params.id;
if(name !== undefined) {
//Find By name here
} else if(id !== undefined) {
//Find by id here
}
}
Hope my answer was helpful.
One approach you can take is determine the value of the req.params.id string if it's a valid ObjectId and then create a query based on the outcome. For example:
app.get('/api/employees/:id', function(req, res){
var query = {};
if (mongoose.Types.ObjectId.isValid(req.params.id)) {
query._id = req.params.id;
} else {
query.name = req.params.id;
}
Employee.findOne(query, function(err, employee){
if(err)
res.send(err);
res.json(employee);
});
});

async.each nested in async.waterfall

I have recently started using async api. Now my requirement is to perform a join on 3 collections
namely fields, scripts and statements. fields can have multiple scripts, and scripts can have multiple statements.
here is what I have tried so far:(to join Fields collection with scripts)
// Array to hold async tasks
var asyncTasks = [];
async.waterfall([
function(callback){
// fetches fields based on some Id and it returns 2 fields
db.fields.find({entity_id: mongojs.ObjectId("54440a448bbbcbb4070131ab")}, function (err, fields) {
console.log(JSON.stringify(fields, null, 2));
callback(null, fields);
})
},
function(arg1, callback){
// arg1 now equals fields
arg1.forEach(function(eachField){
asyncTasks.push(function(callback){
db.scripts.find({fieldId: eachField._id.valueOf()}, function(err, scripts) {
// Async call is done then alert via callback
console.log(JSON.stringify(scripts, null, 2));
callback(null, scripts);
});
});
});
// Now we have an array of functions doing async tasks
// Execute all async tasks in the asyncTasks array
async.parallel(asyncTasks, function(err, results) {
// All tasks are done now
console.log("Scripts" + JSON.stringify(results, null, 2));
callback(null, "done");
});
}
], function (err, result) {
console.log(result);
});
// for the above code here is what i get the output
[
{
"_id": "54440a548bbbcbb4070131ac",
"name": "t1",
"type": "String",
"entity_id": "54440a448bbbcbb4070131ab"
},
{
"_id": "54447f1d20c103981fa1a27c",
"name": "t2",
"type": "String",
"entity_id": "54440a448bbbcbb4070131ab"
}
]
size of array 2
[]
[]
Scripts[
[],
[]
]
done
The above output doesn't print any scripts even though there are 2 scripts in database. My database is is in MongoDB, and i am using NodeJs, MongoJS api. why is db.scripts.find() returning empty array?
Any help is appreciated
I tested this piece of code to see if scripts returning the o/p. Please find below my code
test2();
function test2(){
var getScriptFunction = function(eachField, doneCallback){
if(eachField !== undefined) {
var fieldId = eachField;
console.log(fieldId);
db.scripts.find({fieldId: fieldId}, function (err, result) {
// Async call is done, alert via callback
doneCallback(null, result);
});
}
}
// The array is the id of fields
async.map(["54440a548bbbcbb4070131ac", "54447f1d20c103981fa1a27c"], getScriptFunction, function (err, results) {
// Square has been called on each of the numbers
// so we're now done!
if (err){
console.log("error!" + err);
} else {
console.log("printed from helper function \n" + JSON.stringify(results, null, 2));
}
});
}
This is the o/p of the above code to fetch scripts ran individually
printed from helper function
[
[
{
"_id": "54440a678bbbcbb4070131ad",
"name": "s1",
"fieldId": "54440a548bbbcbb4070131ac"
},
{
"_id": "544af260eb7a486824a5c306",
"name": "s2",
"fieldId": "54440a548bbbcbb4070131ac"
}
],
[]
]
This is how fields look like (db.fields.find().pretty())
[
{
"_id": "54440a548bbbcbb4070131ac",
"name": "t1",
"type": "String",
"entity_id": "54440a448bbbcbb4070131ab"
},
{
"_id": "54447f1d20c103981fa1a27c",
"name": "t2",
"type": "String",
"entity_id": "54440a448bbbcbb4070131ab"
}
]
I was able to solve the problem. there were 2 problems (1) I was having the same name for callback functions i.e. inner and outer callback nested within each other. (2) I had to use toString() and not valueOf()

How to query and update document by using single query?

I have documents likes the following:
{
"_id": "538584aad48c6cdc3f07a2b3",
"startTime": "2014-06-12T21:30:00.000Z",
"endTime": "2014-06-12T22:00:00.000Z",
},
{
"_id": "538584b1d48c6cdc3f07a2b4",
"startTime": "2014-06-12T22:30:00.000Z",
"endTime": "2014-06-12T23:00:00.000Z",
}
As you can see the documents above have startTime and endTime. I need to update some document that don't overlap others. I can make things to work by using two queries:
var event_id = "538584b1d48c6cdc3f07a2b4";
var event = {
startTime: "2014-06-12T21:30:00.000Z"
endTime: "2014-06-12T23:30:00.000Z"
};
Model.count({
_id: {$ne: event_id },
"$or": [
{"$and": [
{"startTime":{"$lte":event.startTime},"endTime":{"$gt":event.startTime}},
{"startTime":{"$lte":event.endTime},"endTime":{"$lt":event.endTime}}
]},
{"$and":[
{"startTime":{"$lte":event.startTime},"endTime":{"$gte":event.startTime}},
{"startTime":{"$lte":event.endTime},"endTime":{"$gte":event.endTime}}
]}
]
}, function (err, count) {
if (err) return next(err);
if (count) {
return next(new Error('Event overlapping'));
}
return Model.findOneAndUpdate({_id: event_id}, event, function (err, event) {
if (err) return next(err);
return res.json(200, event);
});
});
As you can see from the code above I do first query for checking of existing event that could overlaps. And then I do update.
Is it possible to make updating by using single query?

Resources