mongodb express.js find object in array - javascript

I have this database "equipos" that looks like this:
[
"_id" : ObjectId("5ae4ea9f434d9b51dad68813"),
"team_name" : "Alavés",
"nombre_equipo_movil" : "ALA",
"cantidad_integrantes" : 20,
"partidos_jugados" : 29,
"partidos_ganados" : 10,
"partidos_empatados" : 1,
"partidos_perdidos" : 18,
"goles_a_favor" : 26,
"goles_en_contra" : 45,
"players" : [
{
"dorsal" : 1,
"nombre_jugador" : "Fernando Pacheco",
"edad" : 25,
"nacionalidad" : "España",
"posicion" : "Portero",
"goles" : 0,
"asistencias" : 0,
"amarillas" : 4,
"rojas" : 1
}
...
]
...
]
So I want to check if there is a player with "dorsal" 1 in the team Alavés, and I'm doing this
db.equipos.findOne({"team_name": "Alavés" }, {"players": {$elemMatch: {"dorsal": 1l}}})
the problem is that the response to that query when there is no player with dorsal 1 is:
{ "_id" : ObjectId("5ae4ea9f434d9b51dad68813") }
that being the id of the team. The problem is that when I'm sending that query with express like:
dbo.collection("equipos").findOne(
{"team_name": sReq.body.nombre_equipo }, {"players": {$elemMatch: {"dorsal": sReq.body.dorsal}}},
function(err, res){
I cannot compare res to null to see if it couldn't find the player with that dorsal because I always get the ID of the team...
So how can I check that that player does not exist using that response?

Try with .....dorsal:parseInt(sReq.body.dorsal).... –
Because typeof req.body.xxx==="string";but dorsal type:Number.So you must change string to number with parseInt method.

Don't compare res with null, you can compare Object.keys(res).length == 1 for this situation. I really don't know why your query make that result. But I think this will help you.
if(Object.keys(res).length == 1) {
console.log("No player found!");
} else {
console.log("Hey there!");
}

Mongoose findOne method receives an optional second argument with the fields you want to select.
You should query like this:
dbo.collection("equipos").findOne(
{"team_name": sReq.body.nombre_equipo,
"players": {$elemMatch: {"dorsal": sReq.body.dorsal}}
}, function(err, res){
Notice both fields you want to query you pass as the first argument, and the second argument will be the callback, because you don't tell mongoose which fields to select in this case.

Related

Update database entry using mongoose

Hello i am using mongoose.
I have built this query that finds my desired project :
const projects = await ClientManagers.findOne({'project.contactPerson.work_email' : 'testing#email.com'} , { 'project.$.companyName': 1 });
this returns an object from my database like this :
{
'projectName' : 'x',
'companyName' : 'x bv'
}
How can i update the company name to be 'Y bv' instead of 'x bv'.
Assuming this is your document structure,
{
"_id" : ObjectId("5f2ae5a4b1549ac0460920dd"),
"projectName" : "A",
"project" : [
{
"companyName" : "T1",
"contactPerson" : {
"work_email" : "t1#gmail.com"
}
},
{
"companyName" : "T2",
"contactPerson" : {
"work_email" : "t2#gmail.com"
}
}
]
}
Single Update updateOne()
If you know email will be unique and want to update single document then use updateOne().
first is query part to find condition, email t1#gmail.com
second is set/update part, here $ is for array because project is an array, update companyName to T1 Company
await ClientManagers.updateOne(
{ 'project.contactPerson.work_email': 't1#gmail.com' },
{
$set: { "project.$.companyName": "T1 Companmy" }
}
)
Multiple Update updateMany()
If email is not unique and want to update everywhere then use updateMany(), it will update every matching documents.
await ClientManagers.updateMany(
{ 'project.contactPerson.work_email': 't1#gmail.com' },
{
$set: { "project.$.companyName": "T1 Company" }
}
)
Not suggesting update() method to use, because its deprecated in mongoose and will give Deprecation Warnings
, this function is replaced with updateOne(), updateMany() and replaceOne() methods.
Good start. Mongo has better documentation with examples. I suggest you to refer that also.
use update
db.collection.update({companyName:'x bv'}, {"$set":{"companyName":y}})
Mongo is case sensitive. So name should match exactly.
update updates one document. To update multiple, use updateMany or multi:true option with update or findOneAndMondify for one update for find and update case.

MongoDB How to filter db.adminCommand output

does anybody know how to filter mongodb db.adminCommand output? Because if I run this command db.adminCommand({ "currentOp": true, "op" : "query", "planSummary": "COLLSCAN" }) I get a huge JSON output but I'm only interested in some fields ( like secs_running, op, command, $db)
Many thanks!
You can add the filters straight to the command object like the following:
var commandObj = {
"currentOp" : 1,
"waitingForLock" : true,
"$or" : [
{
"op" : {
"$in" : [
"insert",
"update",
"remove"
]
}
},
{
"command.findandmodify" : {
"$exists" : true
}
}
]
};
db.adminCommand(commandObj);
You can see some filter examples on the MongoDB docs: https://docs.mongodb.com/manual/reference/method/db.currentOp/#examples
Just re-read your question and I think you might of meant just projecting fields back from the database that you care about? if that's the case you can just execute a map on top of the current results so you only see what you care about?
db.adminCommand(commandObj).inprog.map(x => x.opid};

Unable to retireve objects from Mongoose-Node

I have a Mongodb database with resume objects like below. I am using a node-express server. And I am querying the mongo database to get objects based on a specific skill. For example: If I query for a skill: jquery, only objects with that skill is returned. The problem is with the get function that is returning objects from the database.
In the highlighted code: If I directly insert the object like:
Resume.find({skills.jQuery : 2},function(err, results){...}
then I get the expected results.
However if I insert it dynamically (skillSet), then it doesnot work. Iit checked the value for skillSet and it give me what I expect('skills.JQuery')
var skillSet = ("'"+'skills.' + req.params.skill +"'");
console.log('skillSet',skillSet) //'skills.jQuery'
Resume.find({skillSet : 2},function(err, results){
Below is the code snippet:
{
"_id" : ObjectId("56031b4353b32084651173fb"),
"uuid" : "acd06792-87c3-4b0e-827a-8bd19d7f9c03",
"creationDate" : ISODate("2015-09-23T21:36:03.728Z"),
"status" : "3",
"name" : "resume_dev",
"__v" : 0,
"skills" : {
"node" : 2,
"react" : 2,
"React" : 3,
"JQUERY" : 2,
"JavaScript" : 15,
"JQuery" : 5,
"Backbone" : 3,
"Node" : 2,
"Angular" : 4,
"Javascript" : 2,
"jQuery" : 17,
"javascript" : 3
}
}
router.get('/skills/:skill', function(req, res){
console.log("req.params.skill",req.params.skill);
var skillSet = ("'"+'skills.' + req.params.skill +"'");
console.log('skillSet',skillSet) //skills.react
Resume.find({skillSet : 2},function(err, results){
console.log('hi');
console.log(skillSet)
console.log(results);
if (err) {
res.status(500).json(err);
}
else {
// console.log("====>",results);
res.status(200).json(results);
// res.render('status',{Resume: JSON.stringify(results)});
}
});
});
When I understand your question correctly, you can do something like this:
var query = {};
query['skills.' + req.params.skill] = 2;
Resume.find(query,function(err, results){
// Do something with the callback
};
EDIT:
If you want to get all numbers greater or equal to 1, you will need $gte. Here are the docs. This is the updated query:
var query = {};
query['skills.' + req.params.skill] = {$gte: 1};
Resume.find(query,function(err, results){
// Do something with the callback
};

Mongoose - Loop an array of embedded docs to .push new value to a field en masse?

I have a doc with an array of embedded docs ("comments"), and an example that looks like this:
{
"_id" : ObjectId("539e9213209e743d107e7202"),
"article" : "article1",
"comments" : [
{
"comment" : "comment1",
"created" : ISODate("2014-06-16T06:43:38Z"),
"_id" : ObjectId("539e921a209e743d107e7203"),
"read" : {
"marked" : false
},
"timesent" : {
"datetime" : "Mon Jun 16 2014 02:43:38 GMT-0400 (EDT)",
"hour" : 2,
"minute" : "43",
"second" : 38,
"am" : true,
"month" : 5,
"day" : 16,
"year" : 2014
}
}
]
}
For each comment in the comments array, is there a way to batch update the field "read" : {"marked" : true}?
Am working with node.js, and have something like this in mind (the questionable portion begins with
if (req.body.readComment) {..
// update the article with this id (accessed by PUT at
// http://localhost:4200/api/v1/articles/:article_id)
.put(function(req, res) {
Article.findById(req.params.article_id, function(err, article) {
if (err)
res.send(err);
if (req.body.comment) {
article.comments.push({
comment : req.body.comment,
timesent :
{
datetime : req.body.datetimeNow,
hour : req.body.hourNow,
minute : req.body.minuteNow,
second : req.body.secondNow,
am : req.body.amNow,
month : req.body.monthNow,
day : req.body.dayNow,
year : req.body.yearNow
},
read :
{
marked : req.body.readComment,
datetime : req.body.readCommentDatetime
},
created : req.body.datetimeNow
});
} // if newComment
if (req.body.readComment) {
var comments = // some sort of .find ?
var embeddedDoc;
for (var i=0, length=comments.length; i < length; i++){
embeddedDoc = comments[i];
embeddedDoc_id = // something to find the embedded doc_id ?
console.log(i);
article.comments.push({ // maybe push to the embedded doc_id
read :
{
marked : req.body.readComment,
datetime : req.body.readCommentDatetime
}
});
};
} // if readComment == true (from ajax .put)
// save the article, and check for errors
article.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Update "' + req.params.article_id });
});
});
})
Well as each comment would need to be identified within the array, the term "Bulk" doesn't really apply as they would be inherently separate. As for being able to just say "Update all of these 'comments' and mark them as true", that is not directly supported.
But on the other hand you can streamline this with Bulk update operations. So for a "list" of "comment" _id values you could do this:
var bulk = collection.initializeOrderedBulkOp();
comments.forEach(function(commentId) {
bulk.find({ "comments._id": commentId }).updateOne({
"$set": { "comments.$.read.marked": false }
});
counter++;
if ( counter % 500 == 0 ) {
bulk.execute(function(err,result) {
// do something with the result
bulk = collection.initializeOrderedBulkOp();
counter = 0;
});
}
});
// Catch any under or over the 500's
if ( counter > 0 )
bulk.execute(function(err,result) {
// do something with the result here
});
That at least avoids you sending an update "over the wire" to the server instance for every single "comment" _id you send into the API. By batching the results this results in less traffic and less time waiting for the response in the callback.
You can likely better this example with "async" so even looping the input list is a non-blocking operation. The batch sizes can vary, but this is just a safe example to stay under the 16MB BSON hard limit, as the whole "request" is equal to one BSON document.

Mongodb/Mongoose: Storing Subdocument of a Variable to a Variable

I am trying to create a shotgun npm command for deleting all topics ever created by a user
This is a sample user entry (users are stored in a collection called 'users'):
{
"__v" : 0,
"_id" : ObjectId("536c4c8fafec055606f01840"), //the id I want to store to a variable and use the variable to find all topics with that id in the 'creator' document
"joinDate" : ISODate("2014-05-09T18:13:28.079Z"),
"lastActiveDate" : ISODate("2014-05-09T18:13:48.918Z"),
"lastSocketId" : null,
"password" : "Johndoe6",
"roles" : [],
"username" : "johndoe6"
}
This is a sample topic entry (topics are stored in a collection called 'topics'):
{
"__v" : 4,
"_id" : 202, //unreliable as these change all the time
"body" : "example topic text",
"commentCount" : 0,
"creator" : ObjectId("536c4c8fafec055606f01840"), //this is the id I want to be found with my variable from a found user
"date" : ISODate("2014-05-14T13:58:13.668Z"),
"editedBy" : ObjectId("536f0392ca01fb0e39364c02"),
"editedDate" : ISODate("2014-05-14T13:59:27.607Z"),
"lastCommentDate" : ISODate("2014-05-14T13:58:13.670Z"),
"tags" : [],
"title" : "test",
"views" : [],
}
Here is a snippet of my code:
exports.invoke = function (shell, options) {
if (!options.confirm) {
shell.warn("Are you sure you want to delete all topics made by {{0}}? (Y/N)".format(options.username));
return shell.setPrompt('confirm', 'purgeTopic', options, 'Are you sure?');
}
shell.db.User.findOne({ username: options.username }, function (err, user) {
var userid = something //this is where I want it to pluck out the user's ID and store it for later
if (err) return shell.error(err);
if (!user) return shell.error("No user {{0}} exists.".format(options.username));
//otherwise
shell.db.Topic.where('creator').equals(userid).remove(function (err) {
As you can see, options.username is a variable that has been typed in by the user doing the command. On the last line I want it to remove topics that have a subdocument 'creator' with the id of the 'user'. How can this be accomplished?
It would simply be:
var userid = user._id;
But you'd want to put that after your if (!user) check in case user is null.

Categories

Resources