I'm working on a NodeJS+Mongodb app.
I've just inserted one record into mongodb using the console client:
db.user.save({myId:11111, myDate: ISODate("2012-04-30T00:00:00.000Z")})
The thing is, when I'm in node.js, I need to know if "myDate" field is really a Date type, in order to perform a data range query, etc.
I tried the following.
1. on the mongo client console:
typeof db.user.myDate --> It returns "Object"
db.user.myDate instanceof Date --> It returns "false"
2. on my Nodejs code,
I'm trying to get the type calling this getTypeMembers
function. (obj comming from a db query)
exports.getTypeMembers = function(obj) {
obj = JSON.parse(JSON.stringify(obj)
for(var _k in obj){
if(Object.prototype.toString.call(obj[_k]) === '[object Array]' ) {
obj[_k] = "Array";
}
else if(typeof(obj[_k])=="object"){
obj[_k] = this.getTypeMembers(obj[_k]);
}else{
obj[_k] = typeof (obj[_k]);
}
}
return obj;
};
What I get in this method is: "String"
, when I need "Date"
Is there any other way to get some kind of "Date"
result?
I finally found my solution.
As @christkv said, once you call a JSON stringify, all original types are definitely lost.
So, thinking in this way, my method getTypeMembers
works perfectly for me.
Notice that, obj parameter is coming from the DB, and also "_id" (mongodb identificator) is directly ommited in order to avoid problems when performs the recursive function:
exports.getTypeMembers = function(obj) {
for(var _k in obj){
if (_k =="_id") continue;
if (Object.prototype.toString.call(obj[_k]) === "[object Number]"){
obj[_k] = "Number";
}else if (Object.prototype.toString.call(obj[_k]) === "[object String]"){
obj[_k] = "String";
}else if (Object.prototype.toString.call(obj[_k]) === "[object Date]"){
obj[_k] = "Date";
} else if(Object.prototype.toString.call(obj[_k]) === '[object Array]' ) {
obj[_k] = "Array";
} else if(typeof(obj[_k])=="object"){
obj[_k] = this.getTypeMembers(obj[_k]);
} else{
obj[_k] = (typeof obj[_k])[0].toUpperCase() + (typeof obj[_k]).slice(1);
}
}
return obj;
};
In the Mongo console part, I only can get the type doing the following:
db.user.find({},{myDate:1}).forEach(function(f) { print (f.myDate instanceof Date) } );
But If I do,
typeof db.user.myDate --> It returns "Object"
db.user.myDate instanceof Date --> It returns "false"
I still don't undertand why.
You can use the $type operator to query for fields of a specific type:
db.col.query({a: {$type: 9}})
9 being the number for the date type, see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24type
As to determining the type inside node.js, it depends on your driver. I've used none, but it might be a specific prototype, like how ObjectId is. Maybe you could examine the object and look for the constructor name.
I'm a little confused by the use of
db.user.myDate
in your example. Are you making this exact call on the Db object that node-mongodb-native is giving you? If so, you should be getting undefined because you are not actually querying the database, but instead checking a property of the Db javascript object (a property that is in almost all certainty not there).
Could you post the code that you are running from the node.js process? I tested out your code, using an identical shell insertion, and once I retrieved the doc from the database in node.js,
doc.myDate instanceof Date
returned true.
I also am not familiar with your application, but it seems ill-advised to me to be querying collections where you do not know the types of the data. Why are you unsure what type of value the other applications are using for the myDate field?
Edit:
var coll = new mongo.Collection(client, 'user');
coll.find({}).toArray(function(err, docs) {
docs.forEach(function (doc) {
console.log(doc);
console.log(doc.myDate instanceof Date);
});
});
logs "true" for me when run in nodejs after an identical shell insert to yours. What happens if you run it?
Judging by your latest edit I believe I see the problem. You are parsing the document into JSON. Unlike BSON, JSON does not support the literal creation and storage of BSON objects. The ISODate
object is a BSON data type.
So when you convert to JSON you actually lose this object.
You can solve this two ways:
$date
property (I believe) which you can check if isset
to see if the field is of type dateIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With