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

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.

Related

mongodb express.js find object in array

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.

How I can get ID of a new record in mongoDB?

There is such a document structure in MongoDB
{
"_id" : ObjectId("58f7d556aa52ce456672a67e"),
"created" : ISODate("2017-04-19T21:23:34.315Z"),
"context_task" : [
{
"task" : "some text ",
"status" : false,
"_id" : ObjectId("58f7d559aa52ce456672a67f")
}
],
"head" : {
"userID" : "58f48037fc894e19a3f7b81b",
"head_task" : "test record "
},
"__v" : 0
}
I add data to the context_task.task using the following query:
task.findOneAndUpdate({"_id": req.body.id_project},
{$push: {'context_task': {'task': req.body.input_task,'status': false}}},{new: true},
function (err, doc) {
if (err) return next(err);
var body = req.body.id_project+","+req.body.input_task;
console.log(doc);
res.status(200).send(body);
});
Tell me, how can I get the context_task._id of a new record after inserting it? In this case, the entire document is returned.
Every mongo document is associated with a default _id, in case not provided it will be ObjectId.
In case you want to use _id value for any other purpose, why don't you have your own _id value, which has to be unique throughout collection. The value can be of any datatype as well as nested also.

Get facebook information in meteor

I'm using Meteor.loginWithFacebook
The user is storing as:
{
"_id" : "cnzMXwmvtF42Dfy4q",
"createdAt" : ISODate("2016-08-31T15:58:00.814Z"),
"services" : {
"facebook" : {
"accessToken" : "randomtoken",
"expiresAt" : 1477842969226,
"id" : "randomid",
"email" : "example#example.com",
"name" : "Name",
"first_name" : "Firstname",
"last_name" : "Lastname",
"link" : "https://www.facebook.com/...",
"gender" : "male",
"locale" : "en_US",
"age_range" : {
"min" : 21
}
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-08-31T15:58:00.818Z"),
"hashedToken" : "randomtoken"
}
]
}
},
"profile" : {
"name" : "Firstname"
}
}
But when I do:
console.log(Meteor.user().services);
It returns as undefined.
But if I do console.log(Meteor.user().profile); it brings the name correctly.
Question
How do I retrieve the facebook information in meteor?
By default, only the username, email and profile object are published to the client. You need to write a publication and subscribe to that on the client to expose the fields you need.
That being said, it may not suit your purposes to publish the services.facebook object directly. If you're using more than one authentication method such as Google or username/password, you'll likely want to standardize your users documents by copying the information you need into different fields.
Here is how I handle a project that uses Facebook, Google, and regular old email/password:
Accounts.onCreateUser(function(options, user) {
// Copy first name and last name from user services
if (user.services.google) {
user.firstName = user.services.google.given_name;
user.lastName = user.services.google.family_name;
} else if (user.services.facebook) {
user.firstName = user.services.facebook.first_name;
user.lastName = user.services.facebook.last_name;
}
// You can use the profile object to pass in user information in a password signup form
if (options && options.profile) {
if (options.profile.firstName) {
user.firstName = options.profile.firstName;
}
if (options.profile.lastName) {
user.lastName = options.profile.lastName;
}
}
return user;
});
Note that it is NOT recommended that you use the profile object to store user data.

adding an object that represents users to an array after signup using passport

I am trying to make a list of username and passwords so that when a user signs in with their credentials they can see all the data that everyone else sees but they still have to use their own credential. I wanted to make a list of objects like this users : [{username : "user1", password : "pass1"}, {username : "user2", password : "pass2"}]. this should be created on signup. I though subdocs would help but I'm not getting what I want. I have this:
var userlist = new mongoose.Schema({username: String, password : String })
var userSchema = new mongoose.Schema({
users : [userlist]
})
and I attempted to add the new users to the array like this:
app.post("/signup", function(req, res){
var user = new User;
user.users.push({username : req.body.username, password : req.body.password})
user.save(function(err){
if(err) return handleError(err);
console.log("success")
})
// User.create(users : [{username : req.body.username, password : req.body.password}], function(err, doc){
// console.log(doc);
// })
res.redirect("/login")
})
this givs me this
> db.users.find().pretty()
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
}
],
"__v" : 0
}
{
"_id" : ObjectId("56ba6225763de71c03199a72"),
"users" : [
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
>
It's making separate documents. I want it to look like this
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
},
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
Having the objectIDs in the subdocs are not so important to me . I just want to group all the users together so that when they go to login I could do something like if the doc is there the credentials are good so continue to other parts of website.
I am not sure if you have resolved you question by now or not, regardless here is the answer to your problem.
Firstly if you don't need _id in subdocument then state that in the schema accordingly and no _id will be created.
var userSchema = new Schema({ username: String, password: String},{ _id: false });
If you use the above schema for user then there should be no _id field in the subdocument.
You should know that to insert a subdocument you need to know the parent for it. If you don't provide the parent while inserting the subdocument then for each insert a new parent is created. In this case parent contains _id and users subdocument. If I have the exact problem, I would go about solving it the following way:
The schema designs remain the same as shown below (I named them differently to avoid confusion):
var userSchema = new Schema({username: String, password: String},{ _id : false });
var userListSchema = new Schema({
users: [userSchema]
});
Now I will declare the parent model as follow:
var UserList = mongoose.model('UserList', userListSchema);
//see below what list gets assigned.
var list;
Now let's assume I have a route handler where I would like to keep adding the users upon sign up something as shown below:
app.get("/newuser/:username/:password", function(req, res) {
//create user model
var User = mongoose.model('User', userSchema);
//load user module, for testing i use params, you can change this to req.body
var user = new User({username: req.params.username, password: req.params.password});
//I would like to find the first document in userlists collection
UserList.findOne({}, function(err, result) {
if(err) console.log(err);
//below if condition is true, if there is one document with users subdoc
if(result) {
console.log('Found existing document with users subdocument. Adding user to array.')
//assign the parent where the subdoc should be inserted to list
list = result;
//there already is a document with subdocument users, so append to it
list.users.push(user);
//save the changed list.
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
} else {
console.log('No document found. Creating one and adding this user to users subdocument.');
// initialize list model with first ever user
list = new UserList({ users: [user] });
//save the new changed list
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
}
})
});
Done. Now when I run the app and access the following URL for the first time
http://127.0.0.1:8080/newuser/user1/pass1
The userslist collection would look as follow:
> db.userlists.find().pretty();
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
}
],
"__v" : 0
}
I would like to access the link with different params as shown below:
http://127.0.0.1:8080/newuser/user2/pass2
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
}
],
"__v" : 1
}
Now I terminate the app and then re-run the app and access the following url:
http://127.0.0.1:8080/newuser/user7/pass7
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
},
{
"password" : "pass7",
"username" : "user7"
}
],
"__v" : 2
}
There you go. I feel bad to see that userlists collection would always always always have one document and its array would keep expanding, maybe not a good practice to solve your issue in this manner. If I were you, I would store each user as a single record and then do the group by or any other aggregation operation.

Javascript literal nested object - refer to top level properties

I'm writing a client side for mobile app that work with restful style web services.
var globApp = {
sessionId : "",
lastActionName: "",
userName : "2victor",
md5Pwd : "1234",
hostApiPath : "http://host/api",
action : {
login : {
scriptPath : "/acc/login",
method : "PUT",
requestParams : {
user : this.userName,
pwd : this.md5pwd
},
responseParams : {
}
},
register : {
scriptPath : "/acc/reg",
method : "POST",
requestParams : {
user : "myUserName",
fname : "myFirstName" ,
lname : "myLastName" ,
email : "mail#mail.com" ,
age : "28" ,
gender : "male" ,
pwd : "1234" ,
priv : "good"
},
responseParams : {
}
}
}
}
Properties userName and md5pwd will be assigned when application start.
What I want to achieve is, to assign this values to user and pwd properties under requestParams object for each action. Of course using this doesn't work and return undefined cause this in that case refers to the nested object if I understand correct.
This requestParams object is sent as JSON by AJAX.
I can define few variables out of this object and use them but I don't want to.
How it can be done?
It can't be done. The object is not available in any way until it has been fully defined. So you can't do it on one single step.

Categories

Resources