2012-08-21 3 views
10

estoy usando expreso y yo estoy buscando una manera conveniente para convertir este tipo de objeto (que viene en la solicitud req.body.myObject):¿Existe alguna característica nativa para convertir JSON basado en cadenas en una instancia de objeto Schema de Mongoose?

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

en una instancia de este esquema:

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

Tenga en cuenta que el primer objeto proviene de la solicitud, por lo que está hecho completamente por cadenas.

¿Hay alguna buena manera de lograrlo? Si no, ¿tendría alguna sugerencia sobre cómo implementar esta característica como middleware?

+1

_ "Tenga en cuenta que el primer objeto proviene de la solicitud, por lo que está hecho completamente por cadenas." _ - ¿Por qué no lo cambia para devolver un número y un booleano en los lugares apropiados? El uso de "tal" en la oración que cité implica que solo se permiten cadenas, pero eso no es cierto si se trata de JSON. (Es decir, JSON en sí es un formato basado en cadenas, pero puede representar números y booleanos, y cuando se analiza el JSON, dichas propiedades se convierten en números y booleanos ...) – nnnnnn

+0

¿Están corregidas las propiedades de su esquema, o lo necesita? ellos dinámicos? – Mahn

+0

@nnnnnn Bueno, el problema es que Express toma la información del formulario 'myObject [name]: name, myObject [someNumber]: 23', y Express construye el myObject configurando de manera predeterminada cada propiedad en una Cadena. – renatoargh

Respuesta

10

Al referirme a este hilo Mongoose : Inserting JS object directly into db Me di cuenta de que sí, hay una función incorporada para esto.

Sólo tiene que construir un nuevo modelo de valores de solicitud de pase (de forma) como parámetros:

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

Convierte automáticamente las cosas para usted!

+1

no necesita tener un "nuevo" delante del contacto. Eso es caro en el nodo. función add (req, res) { Contacto (req.body.contact) .save (function (err) { console.log ("Artículo agregado"); res.send(); }); }; – fino

+0

Hola @fino, gracias por tu consejo! ¿Puede proporcionar algún recurso sobre 'nuevo' que sea costoso para el nodo? ¡Como principiante no he escuchado sobre eso todavía! Gracias – renatoargh

+0

muchas razones Eric tiene algunos buenos aquí http://ericleads.com/2012/09/stop-using-constructor-functions-in-javascript/. para los nodejs, busque la gestión de la memoria del nodojs y el tamaño del almacenamiento dinámico. – fino

0

Siempre que el esquema es estática, se podría teóricamente ir la manera perezosa, no sofisticado y simplemente codificar los valores en lugar de pasar el objeto mismo:

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

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

Posiblemente no sea la respuesta que estabas buscando, pero podría ser algo a considerar si no hay nada mejor disponible.

+1

Como suponía, estoy buscando una manera de hacerlo genéricamente, sin tener que volver a escribir cada vez que escribo un nuevo esquema. – renatoargh

2

Sé que esta respuesta ya ha sido aceptada, pero quería señalar que la mangosta se encarga de la mayor parte del casting para usted ... la mayoría de las veces. Si bien es conveniente que la mangosta haga esto, abstrae el verdadero comportamiento de mongo. Por ejemplo, el meloncillo le permite hacer algo como esto:

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

Sin embargo, si se trató de consultar la base de datos directamente (sin mangosta), esto no trabajo:

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

Esto es porque Los objetos no son cadenas ... son objetos. Internamente, el meloncillo convierte esa cadena en una OBJECTID y luego realiza una consulta en la base de datos para la consulta final se ve un poco como esto:

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

Además, cada camino en un esquema tiene un método "lanzador". Este es un método privado, pero es muy práctico cuando lo necesitas. TENGA EN CUENTA QUE LOS MÉTODOS caster DESCRITOS A CONTINUACIÓN ESTÁN INDOCUMENTADOS Y PUEDEN CAMBIAR SIN ADVERTENCIA. Utilice a su propio riesgo (lo siento por gritar):

// 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); 

¿Por qué sé esto? Porque si desea utilizar algunas de las características más avanzadas de mongo, como la agregación, deberá emitir sus propios valores a medida que crea la interconexión. También he necesitado lanzar valores manualmente para ciertas consultas que usaron el operador $in ... quizás ya no sea necesario. El punto es que si tiene problemas para obtener los resultados que espera, intente emitir los valores usted mismo.

+0

Usted estaría fuera de su mente para usar esto en la producción después de investigar. ¡Ay! –

+1

No con pruebas unitarias ... La gente usa funciones no documentadas con frecuencia, y si prueba su código, está 100% seguro. Si el método desaparece, tu prueba lo revelará mucho antes de que vayas a producción y lo arregles. También te advierto sobre el uso bajo tu propio riesgo. Si no escribe pruebas, ese es su problema y es el riesgo que corre;) –

Cuestiones relacionadas