I am returning a Mongoose document and wish to add some meta data to it before I send it off. I am however unable to add any properties and I am not sure why. I have checked that it is extensible with Object.isExtensible(doc) and it is.
Item.findById(req.params.id).exec(function(err, doc) {
doc.blah = 'hello';
console.log(doc); // No trace of 'blah'. I can change/delete existing props however
})
What could be issue?
Ah.. My object is a Mongoose document which doesn't allow adding properties. The solution is to either convert the returned document to a plain object or to call lean() in the query.
Item.findById(req.params.id).exec(function(err, doc) {
var obj = doc.toObject();
...
});
Item.findById(req.params.id).lean().exec(function(err, doc) {
...
});
Related
I am trying to access the value from an object. But I get the following error.
Object is possibly 'undefined' typescript
My TypeScript code:
import { SqlClient } from 'msnodesqlv8';
declare var require: any;
const sql: SqlClient = require('msnodesqlv8');
const connectionString =
'server=.,1433;Database=emps;Trusted_Connection=Yes;Driver={SQL Server Native Client 11.0}';
const query = 'SELECT * FROM [dbo].[sample] WHERE id = 117';
sql.query(connectionString, query, (err, rows) => {
console.log(rows); // this works fine, but when i try to access its value using object key, it fails
console.log(rows[0].Id); // this fails
});
This works fine in JavaScript. What is the TypeScript way of doing it.
You're getting that error because if the rows array doesn't contain any elements, then rows[0] will be undefined. Two possible solutions:
1) Check that it actually has data, e.g.
if (rows[0]) {
console.log(rows[0].Id)
}
2) Disable the strict or strictNullChecks option in your tsconfig.json (see more here). This will silence the error, but you'll get a runtime error if it actually is undefined, so you may want to check the value instead unless you're absolutely certain it will always have data.
I'm trying to put dynamically function call in Node.js in order to avoid a infinite list of switch-case.
Here a instance of file I want to reach :
var Object = require('../models/Object'); // it's a classic mongoose Schema's object
Here my dynamic function :
/***** post words *****/
router.post('/words', function (req, res) {
var word = req.body ;
var Theme = req.body.theme
[Theme].add[Theme](word, function(err, words) {
if(err) {
res.json(err);
throw err;
}
return res.json(words);
})
})
We suppose a case where the object.name is "Object".
The function I want to build have to call an addPost method in an another file. In order to dynamically call this files I have prepared a computed name property mechanism. Hence I always call the file corresponding to my need. If I have required Object and the user post with a Object's category value, okay it will go on the Object file to compute the Post toward the good destination. So my computed name property look as following :
console.log(req.body.name) // > "Object"
Name = req.body.name
console.log(Name) // > "Object"
Okay now,
When I enter explicitly the name of the object to cal the function, as following :
Object.functionObject()
the function works fine.
BUT if I use a dynamically value call, like :
[Name].functionOf[Name]()
the function returns me :
TypeError: Cannot read property of undefined
Also,
I have try with ${Name} but my console returns me :
TypeError: console.log(...) is not a function
I have tried to install ES6 on Node.js's side sames result for now.
How it is possible since the console.log return me the great value ?
[Theme].add[Theme]()
This code creates an array with Theme as the first value and then calls functionOf, which doesn't exist on the array type. addTheme is actually a syntax error, but the engine never reaches it.
Although I recommend using a switch, I think what you're trying to do is something like this
// define Object1, Object2 with functionObject()
var objectCollection = {};
objectCollection[Object1.name] = Object1;
objectCollection[Object2.name] = Object2;
// Then you get req.body.name later
var objectName = req.body.name;
// and call the method
objectCollection[objectName].functionObject()
This will technically work, but there are a lots of failure possibilities and relying on reflection in this way makes me nervous because your client needs to know the inner workings (object and function names for instance). This is bad.
If the behavior of these objects is that different you should probably separate these into separate routes and let your client decide which it needs if you're making an api.
You could also create a factory to return the proper object and bury the switch statement there.
I am assuming Object contains all those methods
router.post('/words', function (req, res){
var word = req.body ;
var Theme = req.body.theme; // Post
// Object.addPost();
Object[`add${Theme}`](word, function(err, words) {
if(err){
res.json(err) ;
throw err;
}
return res.json(words);
});
// if you want Object.Post.addPost then
Object[Theme][`add${Theme}`](word, function(err, words) {
if(err){
res.json(err) ;
throw err;
}
return res.json(words);
});
});
I have an Object array named users.
The object format in this array looks like this:
var userExample = {pub:{name:'John', id:'100'}, priv:{location:'NYC', phone:'000000'}};
As a restful service, clients may request information of all users.
And obviously I just want to send public information to them.
So I want to serialize my data selectively by keys(priv key will be ignored)
Here is my code snippet:
var users = [];
function censor(key, value) {
if (key == priv) {
return undefined;
}
return value;
}
app.get('/listUsers', function(req, res){
res.end(JSON.stringify(users, censor));
});
When I run these code, an error occurred:
ReferenceError: priv is not defined
I'm a Javascript beginner, please help.
Change priv to "priv".
But your approach is dangerous. In similar conditions I usually create a new object to export and I explicitly copy the properties which should be exported, this way there's no risk of leak on future data structure changes. A white list is always more future proof than a black list.
Newer versions of JSON.stringify() have a replacer array
E.g.
```
JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', only keep "week" and "month" properties
```
Try with:
if (key == "priv")
This should work.
var db = new Dexie(app.settings.unpublishedBooksDb);
db.version(1).stores({
friends: "++id,name,shoeSize"
});
db.open();
db.close();
I have a precreated indexedDB database using the code above, and then on another view in the application, I need to add a row to a table.
var db = new Dexie('myDb');
db.open().then(function() {
console.log ('opened'); //this works
db.friends.add({name:"Fredrik"}); //this doesnt do anything and adding a catch doesn't throw an error either
}).finally(function () {
db.close();
});
I tried using .transaction but still the same. If I try using Chrome's console, I get an error : Cannot read property add of undefined
your second db instance contains no info about what tables it would contain. So the implicit table property (db.friends) is not there. What actually happens is that it throws TypeError: cannot read property 'add' of undefined. If you would catch the call (not just do a finally), you would get that TypeError catched.
What you can do is to reference the friends table by db.table('friends').add ({name: 'Fredrik'}) instead of db.friends.add({name: 'Fredrik'}).
Beware though that defining the database without specifying table schema is not as thorowgly tested and used, so I would recommend using it with a schema defined to avoid other pitfalls as well. If you for architectural reasons still need to do it your way, be aware that transaction scopes works a little different since you cannot use the dynamic implicit tale properties in the transaction scopes either and db.table() currently does not return a transaction-bound Table instance if you are in a transaction scope. You would have to use the old transaction API:
db.transaction('rw', 'friends', function (friends, trans) {
friends.put({name: 'Fredrik'});
});
...instead of:
db.transaction('rw', 'friends', function () {
db.friends.put({name: 'Fredrik'});
});
Best wishes,
David
I'm using Mongoose and I want to remove the _id property from my Mongoose instance before I send the JSON response to the client.
Example:
var ui = _.clone(userInvite);
delete ui["_id"];
console.log(JSON.stringify(ui)); //still has "_id" property, why?
The previous didn't work.
However, if I do:
var ui = JSON.parse(JSON.stringify(userInvite)); //poor man's clone
delete ui["_id"];
console.log(JSON.stringify(ui)); //"_id" is gone! it works!
I don't understand why calling delete on a cloned object using Underscore doesn't work, but if I do the hacky JSON.string/JSON.parse, it works.
Any thoughts on this behavior?
I just came across a similar issue trying to replace _id with id. Doing this worked for me:
Schema.methods.toJSON = function(options) {
var document = this.toObject(options);
document.id = document._id.toHexString();
delete(document._id);
return document;
};
Maybe it will start working if you replace delete ui["_id"] with delete ui._id or use toObject instead of _.clone.
Just to add to the previous answer, there is one more way to achieve the same. 'toObject' function applies transformation to the document which is defined by the schema.options.toObject.transform function, e.g
schema.options.toObject.transform = function(doc, ret) {
ret.id = doc._id;
delete ret._id;
};