2011-04-25 38 views
11

Actualmente estoy jugando con node.js y MongoDB usando el controlador node-mongo-native.Almacenar y recuperar objetos JavaScript en/desde MongoDB

He probado un poco el uso de la consola Mongo almacenando y recuperando objetos JS. Me di cuenta de que si almacena un objeto que contiene funciones/métodos, los métodos y funciones también se almacenarán en la colección. Esto es interesante ya que pensé que las funciones no podían almacenarse en MongoDB (con la excepción de la colección system.js, como sugería el Mongo docs).
Además, no solo almacenará los métodos, sino que en realidad cada método y miembro de la cadena de prototipos completa del objeto. Además de que no me gusta este comportamiento y creo que es poco intuitivo, no debo tenerlo.

Iba a administrar usuarios en una colección de Mongo. Para hacer esto, tengo un objeto Usuario que contiene todos los métodos de los usuarios que funcionan como un prototipo para cada instancia de un usuario. El objeto de usuario solo contendría los atributos de los usuarios.

Si almaceno un usuario en la colección de Mongo, solo quiero almacenar las propiedades propias del objeto de usuario. Sin miembros prototipo y especialmente sin prototipos. Actualmente no veo cómo hacer esto limpiamente. Las opciones que pensé que podrían funcionar son:

  1. creando una copia superficial usando foreach y hasOwnProperty y almacenando esta copia en la colección.
  2. Agregue un atributo de datos a cada usuario que contenga todos los atributos del objeto y se pueda almacenar en la colección.
  3. Esto me vino a la mente al escribir esto: también podría establecer todas las propiedades de los prototipos no enumerables, que debería evitar que se almacenen en la colección.

Sin embargo, tengo los mismos problemas al revés: al cargar un usuario de una colección. AFAIK no hay forma de cambiar un prototipo de objetos en JavaScript después de haber sido creado. Y tampoco hay forma de especificar un prototipo para usar cuando Mongo crea una instancia de objetos recuperados de una colección. Así que, básicamente, siempre obtengo objetos que heredan de Object usando Mongo. Por lo que yo puedo decir que tengo 2 opciones para restaurar un objeto de usuario utilizable a partir de este momento:

  1. crear un objeto nuevo que hereda de usuario y la copia de cada atributo en el objeto de resultado al objeto recién creado. (Compatible con los mecanismos de almacenamiento 1 & 3)
  2. Crea un nuevo objeto heredando del usuario y almacenando el objeto resultante como un atributo de datos en el objeto recién creado. (compatible con el almacenamiento mecanismo 2)

Son mis suposiciones, sobre todo acerca de la posibilidad de especificar un prototipo de resultados de la consulta, ¿correcto? ¿Cuál es la forma correcta de hacerlo, y por qué? Seguramente no soy la primera persona que lucha por almacenar y resucitar objetos en/desde MongoDB usando node.js.

Actualmente me gustaría ir con el enfoque 2/2. Realmente no me gusta, pero es el más eficiente y el único que funciona limpiamente con la API. Sin embargo, preferiría escuchar que la API no hace nada mal, pero lo hago por no saber cómo usarla correctamente. Entonces, por favor, ilumíname :)

Respuesta

8

Recientemente me di cuenta de que, en realidad, es posible cambiar un prototipo de objetos en V8/nodo. Si bien esto no está en el estándar, es posible en varios navegadores y especialmente en V8/node.

function User(username, email) { 
    this.username = username; 
    this.email = email; 
} 

User.prototype.sendMail = function (subject, text) { 
    mailer.send(this.email, subject, text); 
}; 

var o = {username: 'LoadeFromMongoDB', email: '[email protected]'}; 
o.__proto__ = User.prototype; 
o.sendMail('Hello, MongoDB User!', 'You where loaded from MongoDB, but inherit from User nevertheless! Congratulations!'); 

Este se utiliza en todo distintos módulos y plugins - incluso módulos básicos hacen uso de esta técnica, acabase no es estándar ECMAScript. Así que supongo que es seguro usarlo en node.js.

+0

Me entusiasmó leer que fue capaz de almacenar objetos con funciones JS en mongodb (con el controlador mongodb-native?), Pero parece que el controlador se salta los métodos del objeto y solo almacena propiedades con tipos aceptables (cadena, número , array, object, etc ...) para mí. ¿Hiciste algo especial? o leí tu pregunta mal? – nak

+2

No puede almacenar esos métodos en MongoDB. Lo que estoy haciendo es reemplazar el prototipo del objeto JS devuelto por el controlador Mongo a lo que yo quiera que sea. Esto le permitirá llamar a los métodos presentes en el prototipo como si estuvieran presentes en el objeto devuelto por el controlador. Si tiene problemas para entender esto, debe leer sobre cómo funciona la herencia prototípica en JS. –

+0

Ok gracias por aclarar, porque esta sección fue extremadamente engañosa: "Me di cuenta de que si almacena un objeto que contiene functinos/métodos, los métodos y funciones también se almacenarán en la colección. Esto es interesante porque pensé que las funciones podrían no se almacenará en MongoDB (con la excepción de la colección system.js, como sugieren los documentos de Mongo) ". - Entonces sí, las funciones NO se pueden almacenar en MongoDB. – nak

3

No estoy seguro de que te sigo preguntando exactamente ...pero una cosa me vino a la mente: ¿Has comprobado el Mongoose ORM? (http://mongoosejs.com/)

Le ofrece muchas opciones a la hora de definir modelos y métodos. En particular, "Virtuals" podría ser de interés (http://mongoosejs.com/docs/virtuals.html).

De todos modos, ¡espero que ayude a algunos!

+1

Yo conozco a Mongoose. Pero no me gusta Lo que estaba buscando era algún tipo de "mejores prácticas" al trabajar con Mongo y JavaScript en el manejo del almacenamiento de los atributos de los objetos. No es otra biblioteca ¡Sin embargo, gracias por tu respuesta! –

Cuestiones relacionadas