mongoose result's property is undefined, but exist [duplicate] - javascript

I am using mongoose to get person data from database. This is the code i use:
return new Promise((resolve, reject) => {
Person.findOne({}, (err, result) => {
if(err) {
reject(err);
} else {
console.log(result);
console.log(result.firstname);
console.log(result.githubLink);
resolve(result);
}
});
});
This is output from console.log(result)
{ _id: 593c35e6ed9581db3ef85d75,
firstname: 'MyName',
lastname: 'MyLastName',
jobtitle: 'Web Developer',
email: 'foo#example.com',
githubLink: 'https://github.com/myGithub' }
And this is result from console.log(result.firstname); and console.log(result.githubLink);
MyName
undefined
Is this promise somehow messing up with this result? It's really weird because logging only the result shows my github link and logging the link says undefined.

If you have fields present in your database object that are not actually present in the Schema defined for the model, then they will still "log" but you cannot access the values of the property normally.
In most cases you really want to define the item properly in your schema:
githubLink: String
Or you can access properties you deliberately do not want to define using the .get() method:
result.get('githubLink')

Related

GraphQL relational data vs MongoDB document references

I'm new to GraphQL and am trying to learn the best way to use it with MongoDB. GraphQL has a way to define the relationship between types as following:
type Booking {
id: ID!
date: String!
author: [User!]!
event: [Event!]!
}
But, MongoDB also has a way to define the references between documents as following:
event: {
type: Schema.Types.ObjectId,
ref: 'Event'
},
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
If I wanted to retrieve the authors of the Booking, I can either perform the search on the GraphQL's end in the resolver as following:
Booking: {
author(parent, args, ctx, info) {
return users.filter(user => {
return user.id === parent.author;
})
}
},
or I can use a MongoDB find() method on the result to find the authors from the Booking.find() in the resolver as following:
bookings: async () => {
try {
const bookings = await Booking.find();
return bookings.map(booking => {
return //perform MongoDB find() here to get the authors using the references
});
} catch (err) {
throw err;
}
My question is, is it necessary to define the relationship between data on the GraphQL's side as well as on the MongoDB side? Which way of the two mentioned above is a better way to retrieve relational data?

node js and mongodb asynchronous issue

i'm new to mongodb and i'm having problems updating a local variable after a query. i'm using node js and i have a local variable i'm trying to update depending on my query result, but it seems that my functions returns before the query. i understand node js is asynchronous but i'm having trouble dealing with that. you can see my code below:
function userExist(userList, username){
//var usert = new UserSchema()
var exist = false
UserSchema.findOne({userName: username}, function (err, usert) {
if (err) return handleError(err);
if (usert) {
// doc may be null if no document matched
exist = true
}
})
console.log("boolean " + bool)
return exist
// return username in userList
// return query
}
I'm also having a different but unrelated issue where i'm trying to extract a specific value from a query result. my schema is as follow:
//import dependency
var mongoose = require('mongoose')
var Schema = mongoose.Schema
//create new instance of the mongoose.schema. the schema takes an
//object that shows the shape of your database entries.
var UserSchema = new Schema({
userName: String,
userID: String,
Conversations: [
{
conversationID: String,
messages: [
{
message: String,
messageID: String,
sender: String,
time: String
}
]
}
]
})
//export our module to use in server.js
module.exports = mongoose.model('User', UserSchema)
i'm trying to get the values in conversations array, add a new conversation to it and push it back in the database.
An answer to either question would be really helpful and appreciated.
just for clarification this is where i'm using the userExist function:
//Verify Username
socket.on(VERIFY_USER, (nickname, callback)=>{
if(userExist(connectedUsers, nickname)){
console.log("user exist")
callback({ userExist:true, user:null })
}else{
console.log("user does not exist")
callback({ userExist:false, user:createUser({name:nickname, socketId:socket.id})})
}
})
As already pointed out the findOne returns a promise.
You can handle the promise executing callbacks on the success or fail of the findOne result
Define two functions to pass as callbacks
function success(user){
//no error check
//doc has been found
//do something
} ;
function fail(err){
console. log(err)
}
Then in the findOne function body
if (err) return fail(err) ;
//else
return success(user)
OR
you can wrap the userExist function body to return a promise
function userExist(userList, username){
return new Promise(function(resolve, reject){
var exist = false
UserSchema.findOne({userName: username}, function (err, usert) {
if (err) return reject(err);
if (usert) {
// doc may be null if no document matched
exist = true
resolve(exist)
}
})
})
}
And when you call the userExist
userExist(userList, username).then(function(user){
//do something with the user
}).catch(function(reason) {
console.error(reason);
});

Mongoose & MongoDB $Push is correctly updating array of strings, while emptying and refusing to update second array of numbers

I am trying to update an array within a MongoDB collection
It successfully updates when fed the entire array, but the array of numbers breaks and loses all of its values when I use a $Push operation. The array of strings remains intact and successfully updates.
I am trying to update this
var transactionSchema = new Schema({
items: [String],
itemsPrice: [Number],
});
With a single or multiple from value from this.
var itemSchema = new Schema({
itemName: String,
itemPrice: Number,
});
This works when I update using this method
module.exports.updateTransactionById = function (req, res, next) {
Transaction.findOneAndUpdate({_id: req.params.id}, req.body,
{ new: true }, function(err, transaction) {
if (err) return next(err);
if (!transaction) res.status(404).send("No transaction item with that ID!")
return res.status(200).send(transaction);
});
}
// update empty transaction
// RESULT: transaction: {_id=01, items=[a], itemsPrice=[3]}
// update any transaction with some array
// RESULT: transaction: {_id=01, items=[a,b,c], itemsPrice=[1,2,4]}
However, I have to send the entire pre-existing array with each update, which means I would need to query the transactions collection with a GET request before updating it, and that seems unnecessary.
I'm using the $Push method in Mongoose and it doesn't work.
module.exports.updatePushTransactionById = function (req, res, next) {
Transaction.findOneAndUpdate({_id: req.params.id}, { $push: req.body },
{ new: true }, function(err, transaction) {
if (err) return next(err);
if (!transaction) res.status(404).send("No transaction item with that ID!")
return res.status(200).send(transaction);
});
}
// Try updating an empty transaction
//RESULT: transaction: {_id: 01, items=[a], itemsPrice=[]}
// increment subsequent updates
//Result: transaction: {_id: 01, items=[a,b,c,d], itemsPrice=[]}
// Try updating an existing transaction that looks like:
// transaction: {_id: 01, items=[a,b,c,d], itemsPrice=[2,3,4,5]}
// Run push update
//Result: transaction: {_id:01, items=[a,b,c,d,e], itemsPrice=[]
The request body seems to be valid. The casting seems okay, since it accepts the same exact request for the findOneAndUpdate method WITHOUT using a $Push
If this doesn't make sense, here's what I'm trying to accomplish:
A user will click a button to contact the DB and query for the price of an item. The name and price of the item will be fed into a transaction DB. I know holding the details of the transaction in an array is not good, but bear with me.
These are the fetch calls I am using:
GET the price of the item.
function getMenuItemFromDatabase(target) {
var url = '/menus/' + target.id;
return fetch(url, {
method: 'GET'
}).then(function(res){
if(!res.ok) console.log("Error");
else return res.json().then(function(result){
var returnedItem = JSON.parse(result)
return returnedItem[0];
}).catch(function(err){
console.log(err);
throw err;
});
});
}
PUT (by pushing into array) the name and price
function updateTransaction(target){
getMenuItemFromDatabase(target).then(function(menuItem) {
var data = {
items:[menuItem.itemName],
itemsPrice:[menuItem.itemPrice]
}
var url = '/transactions/' + localStorage.transactionID;
fetch(url, {
headers:{
'Content-Type': 'application/json'
},
method: 'PUT',
body: JSON.stringify(data)
}).then(function(res){
if (!res.ok) alert("ERROR!")
else return res.json().then(function(response){
}).catch(function(err) {
console.log(err);
throw(err);
});
});
});
}
I'm pretty confused why this is happening. I've tried looking over the code and playing with the console.log dump in various places, but I'm stuck at this point. I would appreciate any input as to what I must be missing here.
console.log(typeof(req.body.items[0])); // String
console.log(typeof(req.body.itemsPrice[0])); // Number ... so it should work??
I have tried pushing req.body.itemsPrice, req.body.itemsPrice[0], req.body, but the itemsPrice array refuses to update for me.
This is a sample req.body that gets logged by the api
{ items: [ 'Pizza' ], itemsPrice: [ 5.25 ] }
I tried to construct the push query like this:
{ $push: { itemsPrice: req.body.itemsPrice, items: req.body.items} }

return response result of following mongoose's schema

I've been using node (express) with mongoose for a while but I have little clue about mongoose's schema. What I know is it throw you an error and prevent you to do any db operation if the request object (like req.body.firstName) you pass is not exist in the schema.
How can I return my api result according the schema? for example I have a schema like this
const UserSchema = mongoose.Schema({
first: {
type: String
},
last: {
type: String
}
}
module.exports.getAllUsers = (callback) => {
User.find({}, (err,result => {
console.log(result)
})
}
I might not get first and last property in my array, I get whatever data that store in the users collection.
Does it means every response I have to manually do
res.json({
first,
last
})
I'm looking an option to return response that will follow mongoose's schema.

Find one element, use data, then delete it

In my node.js application I'm currently implementing a "Remember Me" functionality. Everything works quite well so far, but I have a problem with mongoose. What I want to do: I have a model named Token with this schema:
var TokenSchema = mongoose.Schema({
token: { type: String },
uid: { type: Schema.Types.ObjectId, ref: 'User' }
});
This is simply a little collection that maps cookie tokens to a UserId. Then I have this function here:
function consumeRememberMeToken(token, fn) {
Token
.findOne({ 'token': token }, (err, result) => {
return (result===null)?fn(null, null):fn(null, result.uid);
})
.remove();
}
What it should do, is this: find the uid for a given token string and return it (if there is a result). But this function should also delete the entry right after returning the uid.
At the moment, the uid from the found token result gets returned properly, but it (the result Token) does not get deleted from the collection with the above code. I don't understand how to remove it right after getting it and using the retrieved uid. I'm completely new to functional programming and I don't understand how and where to delete the token.
You can try db.collection.findOneAndDelete It deletes the document and returns the deleted data, quite the reverse of what you are saying but basically serves your purpose. here are the details.
Also here is the mongoose representation of the same.
Token.findOne({ 'token': token }, (err, result) => {
if(err || !result) return fn(err || "error", null);
else{
var uid = result.uid;
result.remove(function(){
return fn(null, uid);
});
}
})

Categories

Resources