Pass data as object to mongoDb, use it as query and compare - javascript

I have a document in my mongoDB
I pass the object from my frontend (user should type something in input filed, for example he types 'test':
{'countdown': 'test'}
And then I pass it to my backend and want to check if he typed right
app.post('/answ', function(req, res) {
var query = req.body;
Model.find(query
, function(err, result) {
if (err) throw err;
if (result) {
if(result.length!== 0) {
res.json('ok');
} else {
res.json('not found');
}
} else {
res.send(JSON.stringify({
error : 'Error'
}))
}
})
});
So, if key-value pair exist, backend will return ok, otherwise not found.
It works for such simple object, but if I try to pass something like:
{'apilisttask': { 'port': '1', 'host': '2', 'path': '3', 'query': '4' } }
In this example user has 4 input fields, I gather all answers and pass it to the backend, but it doesn't give me ok even if the answers are right.
Could you please advice maybe a better approach to compare the data or how to fix the second comparison?

Since you are trying to find in an embedded document, you can not query embedded doc like that.
To query embedded doc, you need to do something like this:
Model.find({'apilisttask.port':query.apilisttask.port, 'apilisttask.host':query.apilisttask.host, ...}, function(err, result){
// ---
});
This should do the trick.

Related

Mongodb using dynamic fields with $not

I programming in react, mongodb, nodejs and expressjs. I have a problem that I cannot solve. I would like to use dynamic fields from $not on the server. For example, the server gets the column name from the front and it is supposed to return the number of documents where the text is different from an empty string, i.e. ''. I've tried to do something like this(code below), but it doesn't help.
const query = {};
query[type] = { $not: '' };
User.countDocuments(query, (err, data) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true, data: data });
});
You are close, you probably were looking for $ne instead of $not. So changing it to
const query = {};
query[type] = { $ne: '' };
should fix the issue. This would find all documents where the dynamic type field does not equal ''. If you want to do the inverse, i.e. find all documents where the dynamic field equals an empty string, change it to:
query[type] = { $eq: '' };

modified array of object property then pass to front end

I'm using node (express) and want to add a new property before my response (in here I named it as result) get passed to the front-end.
async.parallel(stack, function (err,result) {
result.users[0].price = 100
// console.log(result.users[0]); // I couldn't find price property here I wonder why.
res.json(result);
});
Why is this so?
I tried to alter the other property like password:
console.log(delete result.users[0].password);
console.log(result.users[0]) // password is still present here?
I tried a mini example in fiddle it worked. https://jsfiddle.net/16333z15/
router.get('/json', function (req, res) {
var result = {
users: [{
id: 1,
name: "abc"
}]
};
result.users[0].price = 100;
res.json(result);
});
I have tried this in express and it's worked. You should check the result type, I think it's not tuple.

I have problems with findOneAndUpdate, does not return an error when one of the search data is undefined

When I do a search with "findOneAndUpdate" and one of my search parameters is "undefined" I do not get an error but is the object searched. this is the code:
var q = Q.defer();
var findOneQuery = {
_id: restId,
versionId: document.version // if this parameter is undefined
};
this.findOneAndUpdate(findOneQuery, {$set: document, $inc: {versionId: 1}}, {upsert: true, new: true}, function (updateError, updateDocument) {
if (updateError) {
q.reject(updateError);
}
else {
q.resolve(updateDocument);
}
});
return q.promise;
I think it should return an error if I'm wrong What should I do to search for the two parameters sent and not just by one of them?
You can easily write a wrapper method around findOneandUpdate that would precisely do what you want with your reqs.
function myFindOneAndUpdate(monObj,query,update,options,callback){
//validateINput check if the params in query object are undefined
if(validateInput(query)){
monObj.findOneAndUpdate(query,update,options,callback)
}else{
throw new Error('InvalidInput');
}
}
If parameter is undefined, then mongodb try to find records in which parameter is undefined. So it would not throw any error.
if you want that versionId should be never null/undefined. then you can validate inputs before passing to db query.
You can use this module:
https://www.npmjs.com/package/validator

Mongodb save into nested object?

I can't get my req.body inserted into my mongodb collection.
I have this route that triggers the add method and inside I am trying to figure out a query to save the req.body into a nested collection array
router.post('/api/teams/:tid/players', player.add);
add: function(req, res) {
var newPlayer = new models.Team({ _id: req.params.tid }, req.body);
newPlayer.save(function(err, player) {
if (err) {
res.json({error: 'Error adding player.'});
} else {
console.log(req.body)
res.json(req.body);
}
});
}
Here is an example document
[
{
"team_name":"Bulls",
"_id":"5367bf0135635eb82d4ccf49",
"__v":0,
"players":[
{
"player_name":"Taj Gibson",
"_id":"5367bf0135635eb82d4ccf4b"
},
{
"player_name":"Kirk Hinrich",
"_id":"5367bf0135635eb82d4ccf4a"
}
]
}
]
I can't figure out how to insert/save the POST req.body which is something like
{
"player_name":"Derrick"
}
So that that the new req.body is now added into the players object array.
My question is how do I set the mongodb/mongoose query to handle this?
P.S I am obviously getting the error message because I don't think the query is valid, but it's just kind of an idea what I am trying to do.
Something like this is more suitable, still doesn't work but its a better example I guess
var newPlayer = new models.Team({ _id: req.params.tid }, { players: req.body });
If you created a Team model in Mongoose then you could call the in-built method findOneAndUpdate:
Team.findOneAndUpdate({ _id: req.params.tid },
{ $addToSet: { players: req.body} },
function(err, doc){
console.log(doc);
});
You could do findOne, update, and then save, but the above is more straightforward. $addToSet will only add if the particular update in question doesn't already exist in the array. You can also use $push.
The above does depend to an extent on how you have configured your model and if indeed you are using Mongoose (but obviously you asked how it could be done in Mongoose so I've provided that as a possible solution).
The document for $addToSet is at http://docs.mongodb.org/manual/reference/operator/update/addToSet/ with the relevant operation as follows:
db.collection.update( <query>, { $addToSet: { <field>: <value> } } );

How to exclude one particular field from a collection in Mongoose?

I have a NodeJS application with Mongoose ODM(Mongoose 3.3.1). I want to retrieve all fields except 1 from my collection.For Example: I have a collection Product Which have 6 fields,I want to select all except a field "Image" . I used "exclude" method, but got error..
This was my code.
var Query = models.Product.find();
Query.exclude('title Image');
if (req.params.id) {
Query.where('_id', req.params.id);
}
Query.exec(function (err, product) {
if (!err) {
return res.send({ 'statusCode': 200, 'statusText': 'OK', 'data': product });
} else {
return res.send(500);
}
});
But this returns error
Express
500 TypeError: Object #<Query> has no method 'exclude'.........
Also I tried, var Query = models.Product.find().exclude('title','Image'); and var Query = models.Product.find({}).exclude('title','Image'); But getting the same error. How to exclude one/(two) particular fields from a collection in Mongoose.
Use query.select for field selection in the current (3.x) Mongoose builds.
Prefix a field name you want to exclude with a -; so in your case:
Query.select('-Image');
Quick aside: in JavaScript, variables starting with a capital letter should be reserved for constructor functions. So consider renaming Query as query in your code.
I don't know where you read about that .exclude function, because I can't find it in any documentation.
But you can exclude fields by using the second parameter of the find method.
Here is an example from the official documentation:
db.inventory.find( { type: 'food' }, { type:0 } )
This operation returns all documents where the value of the type field is food, but does not include the type field in the output.
Model.findOne({ _id: Your Id}, { password: 0, name: 0 }, function(err, user){
// put your code
});
this code worked in my project. Thanks!! have a nice day.
You could do this
const products = await Product.find().select(['-image'])
I am use this with async await
async (req, res) => {
try {
await User.findById(req.user,'name email',(err, user) => {
if(err || !user){
return res.status(404)
} else {
return res.status(200).json({
user,
});
}
});
} catch (error) {
console.log(error);
}
In the updated version of Mongoose you can use it in this way as below to get selected fields.
user.findById({_id: req.body.id}, 'username phno address').then(response => {
res.status(200).json({
result: true,
details: response
});
}).catch(err => {
res.status(500).json({ result: false });
});
I'm working on a feature. I store a userId array name "collectedUser" than who is collected the project. And I just want to return a field "isCollected" instead of "collectedUsers". So select is not what I want. But I got this solution.
This is after I get projects from database, I add "isCollected".
for (const item of projects) {
item.set("isCollected", item.collectedUsers.includes(userId), {
strict: false,
})
}
And this is in Decorator #Schema
#Schema({
timestamps: true,
toObject: {
virtuals: true,
versionKey: false,
transform: (doc, ret, options): Partial<Project> => {
return {
...ret,
projectManagers: undefined,
projectMembers: undefined,
collectedUsers: undefined
}
}
}
})
Finally in my controller
projects = projects.map(i => i.toObject())
It's a strange tricks that set undefined, but it really work.
Btw I'm using nestjs.
You can do it like this
const products = await Product.find().select({
"image": 0
});
For anyone looking for a way to always omit a field - more like a global option rather than doing so in the query e.g. a password field, using a getter that returns undefined also works
{
password: {
type: String,
required: true,
get: () => undefined,
},
}
NB: Getters must be enabled with option { toObject: { getters:true } }
you can exclude the field from the schema definition
by adding the attribute
excludedField : {
...
select: false,
...
}
whenever you want to add it to your result,
add this to your find()
find().select('+excludedFiled')

Categories

Resources