javascript undefined, when I just logged it - javascript

So I just posted a Q about a nested date object and got a speedy answer, felt kinda silly, it was obvious, but no sooner did I get one correct response when something else throw an undefined error.
I'm inside a method call that "finds" a key, and then I want to use the data in that key for other things
This :
Coupon.findKey( req.params._key, (err, key) => {
if ( err ) {
return res.status(400).send(err);
}
console.log('---------- key '+key+'----------');
});
Gives me this:
---------- key { _id: 5a72c5cbe617796370219fb3, token: 'mWJhRlytyjaxztWfsP6tpH7PccEpSfkemZqyt9pf26e4fI1b32e5Qun8LfLKmkhXMytFtB7QYHHLUgGV0V7AwUB055Cp78Old2IrBHlmgDDFl6qYxe05cgTFLzjmzuAZ', user_id: 5a72c5cbe617796370219fb2, type: 'registration', __v: 0, date: { redeemed: null, issued: 2018-02-01T07:46:19.449Z } }----------
clearly - Coupon.findKey() returned an object. That object "appears" to have _id and user_id available.
However if I do this
Coupon.findKey( req.params._key, (err, key) => {
if ( err ) {
return res.status(400).send(err);
}
console.log('---------- key '+ key._id +'----------');
});
I get
---------- key undefined----------
WHAT THE HECK. Javascript, you break my will...
Help anyone....
And my frustration mounts
mongoose not returning a record

key seems to be an array.
Get the first entry from that array: key[0]._id
key[0] is:
{
"_id": "5a72c5cbe617796370219fb3",
"key": "mWJhRlytyjaxztWfsP6tpH7PccEpSfkemZqyt9pf26e4fI1b32e5Qun8LfLKmkhXMytFtB7QYHHLUgGV0V7AwUB055Cp78Old2IrBHlmgDDFl6qYxe05cgTFLzjmzuAZ",
"user_id": "5a72c5cbe617796370219fb2",
"type": "registration",
"__v": 0,
"date": {
"redeemed": null,
"issued": "2018-02-01T07:46:19.449Z"
}
}

Related

How do I parse one part of a nested query result? (Javascript and MySQL)

I am trying to get a nested structure from a MySQL query, and as a result of using JSON_OBJECT, one section of my return data is stringified. The data I am currently getting looks as follows:
[
{
"id": 3,
"body": "Does this product run big or small?",
"date_written": 1608535907,
"asker_name": "jbilas",
"helpful": 8,
"reported": 0,
"answers": null
},
{
"id": 4,
"body": "How long does it last?",
"date_written": 1594341317,
"asker_name": "funnygirl",
"helpful": 6,
"reported": 0,
"answers": "{\"65\": {\"id\": 65, \"body\": \"It runs small\", \"date\": 1605784307, \"helpful\": 1, \"reported\": 0, \"answerer_name\": \"dschulman\"}, \"89\": {\"id\": 89, \"body\": \"Showing no wear after a few months!\", \"date\": 1599089610, \"helpful\": 8, \"reported\": 0, \"answerer_name\": \"sillyguy\"}}"
},
{etc},
{etc}]
Before sending the result of my database query back to the client, I need to parse the answers value. My initial thought was to make the result a promise, then use a forEach loop to run through each object and parse 'answers' if it is not undefined. My code to do that is organized as follows:
db.query(query, [req.query['product_id'], req.query['count']], (error, results) => {
if (error) {
console.log('err err ', error);
}
if (!results[0]) {
res.json('No questions found')
} else {
console.log(results)
Promise.resolve(results.forEach(result => {
if (result['answers'] !== undefined) {
JSON.parse(result['answers']);
}
return results;
}))
.then(results => {
console.log(results)
})
res.json(results.splice(0, req.query['count']));
}
})
The console log in my 'then' block returns undefined. I also tried using results.map(), but this logged a bunch of empty arrays in the then block. Any advice on how to parse the 'answers' values when they are not null for an array of objects much appreciated!
Just a thought, have you tried just iterating results and updating the answers property without a Promise?:
db.query(query, [req.query['product_id'], req.query['count']], (error, results) => {
if (error) {
console.log('err err ', error);
}
if (!results[0]) {
res.json('No questions found')
} else {
console.log(results)
results.forEach(result => {
result.forEach((obj) => {
obj.answers = JSON.parse(obj.answers);
});
});
res.json(results.splice(0, req.query['count']));
}
});

MongoDB get Value of a Field in NodeJS

I'm new to MongoDB and I try to create a User Coin System for discord with NodeJS. There is no problem in adding new documents to the collection but i can not access only a single value. I want to return the value of "coins" to let the user see his coins.
I'm using the find() method and it returns a document:
{
"_id": {
"$oid": "5f875963b622f72c3850da6f"
},
"username": "Test",
"userID": "1234",
"messages": {
"$numberInt": "22"
},
"coins": {
"$numberInt": "210"
},
"__v": {
"$numberInt": "0"
}
}
I tried to access "coins" with dot but it always returns undefined:
User.find({userID: message.author.id}).exec((err, res) => {
if (err) return console.log(err);
let embed = new Discord.RichEmbed()
.setTitle(message.author.tag)
.setColor("#4000FF")
.setThumbnail(message.author.displayUserAvatarURL);
//User has no Coins
if(!res){
embed.addField("Coins", "0", true);
return message.reply(embed);
}else {
//res.coins are undefined. Returning 'res' is the whole document from above.
embed.addField("Coins", res.coins , true);
return message.reply(embed);
}
})
1. Try using findOne
2. check your userId in db is string format so it could be a problem .
3. Convert your message.author.id to string before finding. then you will find everything in your result object
let user_id=message.author.id;
User.findOne({userID: user_id.toString()},function(error, body) {
if (error){
result(error, null);
}
var results= body;
})

Node.js: Cannot read property 'then' of undefined (nested query)

I'm trying to update a field in a MongoDB collection which has nested documents. I have to increase a certain value. The update query works just fine, but I need to nest it in another query where I get the current value, so I could increase it.
The nesting worked just fine when I used a faulty find() method. I realized I must use aggregate(). I can't get it working, the method returns undefined for some reason. I've tried the same aggregate query in the shell and it works, so it has to do something with the Node.js
The function that fails:
static addPointsToUser(mainId, userId, pointsToAdd) {
const db = getDb();
function getCurrent() {
db.collection('mycoll')
.aggregate([
{ $match: { _id: mainId } },
{ $unwind: '$userPoints' },
{ $match: { 'userPoints._id:': userId } },
{ $group: { _id: 'userPoints._id', userPoints: { $push: '$userPoints.points' } } }
])
}
function updateNew(newPoints) {
db.collection('mycoll')
.updateOne(
{ _id: mainId },
{ $set: { "userPoints.$[elem].points": newPoints } },
{
multi: true,
arrayFilters: [{ "elem._id": userId }]
}
)
}
return getCurrent()
.then(result => {
console.log(result);
const newPoints = result.userPoints[0];
return updateNew(newPoints)
.then(result => {
console.log(result);
return result;
})
})
}
The document looks like this:
{
"_id": ObjectId("5d4048f56a895612acabe0a9"),
// Some other fields
"userPoints": [
{ "_id": "manualID1", "points": 80 },
{ "_id": "manualID2", "points": 90 }
]
}
Expected aggregate result:
{ "_id" : "manualID1", "userPoints" : [ 90 ] }
Mongo shell gives the result seen above.
Actual result:
TypeError: Cannot read property 'then' of undefined
If I log the aggregate result it prints and empty array ( [] ).
Your methods getCurrent and updateNew are not returning anything. Which mean you are using .then() on something which is undefined as stated by your error message.
Adding a return statement before db.collection('mycoll') should help you with that.

I want to remove the property inside a object in mongodb

I have this bson doc in a collection. I want to remove a key based on dynamic value.
{
"_id": ObjectId("53ccff9bbb25567911f208a2"),
"image": {
"image1": "5213423424234.jpg",
"image2": "5213423424235.jpg",
"image3": "5213423424236.jpg"
}
}
In request I will get "image1"
temp/5bb3685b663c6f001d14c5da/dl/image1
I saved the key in a variable
let keyid = req.params.k_id
If I call the key directly, this works.
let qry = {
_id: mongojs.ObjectId(req.params.p_id)
}
let update = {
$unset: {
"image.image1": ""
}
}
db.inventory.findAndModify({
query: qry,
update: update,
safe: true
}, function (err, doc) {
if (err) {
res.status(500).json({
"success": false,
"error": err
})
return
}
res.status(200).json({
"success": true,
"message": "Deleted image key"
})
return
})
But since the key is dynamic, I am not able to find the solution with various possibilities
// Try1
$unset: {
'image.' + keyid: ""
},
// Try2
$unset: {
`image.${keyid}`: ""
}
You can try to change the update obj like this
let update = {}
update["$unset"] = {};
update["$unset"]['image.' + keyid] = '';
You need to build up your $unset object programmatically:
This question was answered here: using a variable in mongodb update

Returning dates / server timestamps in cloud callable functions

I'm using a callable function from a client app to retrieve some data from firestore. The data is created using:
projectData = {
created: firebase.firestore.FieldValue.serverTimestamp(),
...otherData
}
firebase.firestore().collection(projectsCollection).add(projectData)
And I can see the timestamp is correctly saved in the firestore console. The callable function does some other things and has error handling, but the data retrieval is done like this (using lodash to expand each document into an object to return to the client):
const projectRef = firestore.collection(gProjectsCollection).orderBy('created')
return projectRef.get().then(snapshot => {
return {
projects: _.chain(snapshot.docs)
.keyBy('id')
.mapValues(s => s.data())
.value()
}
})
This mostly works, but the returned object has a mangled created property (shown here in functions shell output):
RESPONSE RECEIVED FROM FUNCTION: 200, {
"result": {
"projects": {
"XcRyQyaxLguRdbNmxQdn": {
"name": "c",
"description": "c",
"created": {
"_seconds": 1543405587,
"_nanoseconds": 169000000
}
}
}
}
}
I'm presuming this is because the callable function uses JSON.stringify() internally, and the server timestamp isn't converted correctly. I tried explicitly converting the timestamp to a date like this:
return projectRef.get().then(snapshot => {
return {
exVersion,
exId,
projects: _.chain(snapshot.docs)
.keyBy('id')
.mapValues(s => s.data())
.forEach(d => { d.created = d.created.toDate() })
.value()
}
})
but now I get an empty object back:
RESPONSE RECEIVED FROM FUNCTION: 200, {
"result": {
"projects": {
"XcRyQyaxLguRdbNmxQdn": {
"name": "c",
"description": "c",
"created": {}
}
}
}
}
I suspect the real problem here is that callable functions aren't set up to return date objects. If I go one more step and convert the timestamp into a string, I finally get something back in the client:
return projectRef.get().then(snapshot => {
return {
exVersion,
exId,
projects: _.chain(snapshot.docs)
.keyBy('id')
.mapValues(s => s.data())
.forEach(d => { d.created = d.created.toDate().toISOString() })
.value()
}
})
gives:
RESPONSE RECEIVED FROM FUNCTION: 200, {
"result": {
"exVersion": 9,
"exId": null,
"projects": {
"XcRyQyaxLguRdbNmxQdn": {
"name": "c",
"description": "c",
"created": "2018-11-28T11:46:27.169Z"
}
}
}
}
I couldn't find anything in the documentation for callable functions about special handling for dates, but am I missing something in how this should be done?
Some further analysis in the callable function suggests JSON.stringify() is involved, but isn't the whole problem:
console.log(JSON.stringify(d.created)):
info: {"_seconds":1543405587,"_nanoseconds":169000000}
JSON.stringify(d.created.toDate())
into: "2018-11-28T11:46:27.169Z"
So calling d.created.toDate() should be sufficient. But I've had other cases where Date objects are just not returned by callable functions, e.g.:
const testObject = {
some: 'thing',
d: new Date()
}
console.log('JSON:', JSON.stringify(testObject))
return projectRef.get().then(snapshot => {
return {
testObject,
projects: _.chain(snapshot.docs)
.keyBy('id')
.mapValues(s => s.data())
.forEach(d => { console.log('d.created is:', JSON.stringify(d.created.toDate())); d.created = d.created.toDate() })
.value()
}
})
Note in the output below, the logged results of JSON.stringify() on date objects seems to work, but when those objects are contained within the object returned from the function, they both come out as empty objects:
firebase > getAllProjects({uid: 1234})
Sent request to function.
firebase > info: User function triggered, starting execution
info: JSON: {"some":"thing","d":"2018-11-28T13:22:36.841Z"}
info: Got 1 projects
info: d.created is: "2018-11-28T11:46:27.169Z"
info: Execution took 927 ms, user function completed successfully
RESPONSE RECEIVED FROM FUNCTION: 200, {
"result": {
"testObject": {
"some": "thing",
"d": {}
},
"projects": {
"XcRyQyaxLguRdbNmxQdn": {
"description": "c",
"created": {},
"name": "c"
}
}
}
}
From the documentation:
To send data back to the client, return data that can be JSON encoded.
Since Date is not a JSON type, you will have to use your own serialization format for it (at least if you want it to be reliable/portable). From the linked answer it sounds like Date.toJSON is a great candidate for that.

Categories