Renato Gama
Renato Gama

Reputation: 16519

Is there a native feature to convert string based JSON into Mongoose Schema object instance?

I am using Express and I am looking for a convenient way to convert this kind of object (which comes on the request req.body.myObject):

{
  "name": "Foo",
  "someNumber": "23",
  "someBoolean": "on"
}

Into an instance of this Schema:

var myObjectSchema = new Schema({
    name: String,
    someNumber: Number,
    someBoolean: Boolean
});

Notice that the first object comes from the request, so its made entirely by Strings.

Is there some nice way to achieve this? If not, would you have any suggestions on how to implement this feature as a middleware???

Upvotes: 11

Views: 10600

Answers (3)

Ryan Wheale
Ryan Wheale

Reputation: 28380

I know this answer has already been accepted, but I wanted to point out that mongoose takes care of most of the casting for you... most of the time. While it's convenient that mongoose does this, it abstracts away the true behavior of mongo. For example, mongoose lets you do something like this:

PersonModel.findById("4cdf00000000000000007822", ...);

However, if you tried to query the database directly (without mongoose), this would not work:

PersonCollection.find({_id: "4cdf00000000000000007822"}, ...);

This is because ObjectIds are not strings... they are objects. Internally, mongoose converts that string to an ObjectId and then performs a query against the database so that the final query looks kinda like this:

PersonCollection.find({_id: ObjectId("4cdf00000000000000007822")}, ...);

Also, each path in a schema has a "caster" method. This is a private method, but it's darn handy when you need it. PLEASE NOTE THAT THE caster METHODS DESCRIBED BELOW ARE UNDOCUMENTED AND CAN CHANGE WITHOUT WARNING. USE AT YOUR OWN RISK (sorry for yelling):

// Use PersonModel.schema.paths() to get all paths and loop over them if you want
var key = "name";
var pathObj = PersonModel.schema.path( key );
if( !pathObj ) pathObj = PersonModel.schema.virtualpath( key );
if( !pathObj ) { /* not found: return, continue, exit, whatever */ }

// UNDOCUMENTED: USE AT YOUR OWN RISK
var caster = pathObj.caster || pathObj;
var castedValue = caster.cast( req.body.name );

Why do I know this? Because if you want to use some of the more advanced features of mongo such as aggregation, you will need to cast your own values as you build the pipeline. I have also needed to manually cast values for certain queries which used the $in operator... maybe this is not needed any more. Point is, if you are having trouble getting the results you expect, try casting the values yourself.

Upvotes: 2

Renato Gama
Renato Gama

Reputation: 16519

By referring to this thread Mongoose : Inserting JS object directly into db I figured out that yes, theres a built in feature for this.

You simply build a new model passing request values (from the form) as parameters:

function add(req, res){
    new Contact(req.body.contact).save(function(err){
        console.log("Item added");
        res.send();
    });
};

It automatically converts stuff for you!

Upvotes: 11

Mahn
Mahn

Reputation: 16585

Provided the schema is static, one could theoretically go the lazy, non-sophisticated way and just hardcode the values instead of passing the object itself:

var someObject = {
    name: "Foo",
    someNumber: "23",
    someBoolean: "on"
}

var myObjectSchema = new Schema({
    name: someObject.name,
    someNumber: parseInt(someObject.someNumber, 10),
    someBoolean: (someObject.someBoolean == "on")
});

Possibly not the answer you were looking for, but might be something to consider if nothing better is available.

Upvotes: 0

Related Questions