Los dos tipos de objetos parecen estar tan cerca el uno del otro que ambos parecen redundantes. ¿De qué sirve tener ambos esquemas y modelos de?¿Por qué Mongoose tiene esquemas y modelos?
Respuesta
A menudo, la forma más fácil de responder a este tipo de preguntas es con un ejemplo. En este caso, alguien ya lo ha hecho por mí :)
Echa un vistazo aquí:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
EDIT: El post original (como se menciona en los comentarios) parece que ya no existe , entonces lo estoy reproduciendo a continuación. Si alguna vez regresa, o si se acaba de mudar, házmelo saber.
Se da una descripción decente de la utilización de esquemas dentro de los modelos de mangosta y por qué desea hacerlo, y también muestra cómo empujar tareas a través del modelo, mientras que el esquema es todo acerca de la estructura, etc.
Publicación original:
Comencemos con un ejemplo simple de incrustación de un esquema dentro de un modelo.
var TaskSchema = new Schema({
name: String,
priority: Number
});
TaskSchema.virtual('nameandpriority')
.get(function() {
return this.name + '(' + this.priority + ')';
});
TaskSchema.method('isHighPriority', function() {
if(this.priority === 1) {
return true;
} else {
return false;
}
});
var ListSchema = new Schema({
name: String,
tasks: [TaskSchema]
});
mongoose.model('List', ListSchema);
var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
he creado una nueva TaskSchema
objeto con información básica de una tarea podría tener. Un Mongoose virtual attribute está configurado para combinar convenientemente el nombre y la prioridad de la Tarea. Solo especifiqué un getter aquí, pero los setters virtuales también son compatibles.
También definí un método de tarea simple llamado isHighPriority
para demostrar cómo funcionan los métodos con esta configuración.
En la definición ListSchema
notará cómo la tecla de tareas está configurada para contener una matriz de objetos TaskSchema
. La clave de tarea se convertirá en una instancia de DocumentArray
que proporciona métodos especiales para tratar con documentos integrados de Mongo.
Por ahora solo pasé el objeto ListSchema
en mongoose.model y dejé TaskSchema. Técnicamente, no es necesario convertir TaskSchema
en un modelo formal ya que no lo guardaremos en su propia colección. Más adelante, le mostraré cómo no perjudicará nada si lo hace y puede ayudar a organizar todos sus modelos de la misma manera, especialmente cuando comienzan a abarcar múltiples archivos.
Con la configuración del modelo List
, agreguemos un par de tareas y guárdelas en Mongo.
var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
sampleList.tasks.push(
{name:'task one', priority:1},
{name:'task two', priority:5}
);
sampleList.save(function(err) {
if (err) {
console.log('error adding new list');
console.log(err);
} else {
console.log('new list successfully saved');
}
});
Las tareas de atributos en la instancia de nuestro modelo List
(simpleList
) funciona como una matriz regular JavaScript y podemos añadir nuevas tareas al mismo mediante empuje. Lo importante es notar que las tareas se agregan como objetos regulares de JavaScript. Es una distinción sutil que puede no ser inmediatamente intuitiva.
Puede verificar desde el shell Mongo que la nueva lista y las tareas se guardaron en mongo.
db.lists.find()
{ "tasks" : [
{
"_id" : ObjectId("4dd1cbeed77909f507000002"),
"priority" : 1,
"name" : "task one"
},
{
"_id" : ObjectId("4dd1cbeed77909f507000003"),
"priority" : 5,
"name" : "task two"
}
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }
Ahora podemos usar el ObjectId
para levantar la Sample List
e iterar a través de sus tareas.
List.findById('4dd1cbeed77909f507000001', function(err, list) {
console.log(list.name + ' retrieved');
list.tasks.forEach(function(task, index, array) {
console.log(task.name);
console.log(task.nameandpriority);
console.log(task.isHighPriority());
});
});
Si ejecuta esa última parte del código que obtendrá un error que dice el documento incrustado no tiene un método isHighPriority
. En la versión actual de Mongoose, no puede acceder directamente a los métodos en esquemas incrustados. Hay un open ticket para solucionarlo y, después de hacerle la pregunta al Grupo Mongoose Google, manimal45 publicó una útil solución para usar por el momento.
List.findById('4dd1cbeed77909f507000001', function(err, list) {
console.log(list.name + ' retrieved');
list.tasks.forEach(function(task, index, array) {
console.log(task.name);
console.log(task.nameandpriority);
console.log(task._schema.methods.isHighPriority.apply(task));
});
});
Si ejecuta ese código, debería ver la siguiente salida en la línea de comandos.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Con esa solución alternativa en mente vamos a centrar la TaskSchema
en un modelo de mangosta.
mongoose.model('Task', TaskSchema);
var Task = mongoose.model('Task');
var ListSchema = new Schema({
name: String,
tasks: [Task.schema]
});
mongoose.model('List', ListSchema);
var List = mongoose.model('List');
La definición TaskSchema
es lo mismo que antes, así que me fui a cabo. Una vez que se convirtió en un modelo, aún podemos acceder a su objeto Schema subyacente mediante la notación de puntos.
Creemos una nueva lista e incorporemos dos instancias de modelo de tarea dentro de ella.
var demoList = new List({name:'Demo List'});
var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});
demoList.tasks.push(taskThree.toObject(), taskFour.toObject());
demoList.save(function(err) {
if (err) {
console.log('error adding new list');
console.log(err);
} else {
console.log('new list successfully saved');
}
});
Como estamos incrustación de las instancias de modelo de tareas en la lista que llamamos toObject
en ellos para convertir sus datos en llano JavaScript objetos que el List.tasks
DocumentArray
está esperando. Cuando guarde instancias de modelo de esta manera, sus documentos incrustados contendrán ObjectIds
.
El ejemplo del código completo es available as a gist. Afortunadamente estas soluciones ayudan a suavizar las cosas a medida que Mongoose continúa desarrollándose. Todavía soy bastante nuevo para Mongoose y MongoDB, así que no dude en compartir mejores soluciones y sugerencias en los comentarios. ¡Feliz modelado de datos!
El esquema es un objeto que define la estructura de los documentos que se almacenarán en su colección MongoDB; le permite definir tipos y validadores para todos sus elementos de datos.
El modelo es un objeto que le da fácil acceso a una colección con nombre, lo que le permite consultar la colección y usar el esquema para validar cualquier documento que guarde en esa colección. Se crea al combinar un esquema, una conexión y un nombre de colección.
originalmente redactada por Valeri Karpov, MongoDB Blog
no creo que la respuesta aceptada en realidad responde a la pregunta que se plantea. La respuesta no explica por qué Mongoose ha decidido exigir a un desarrollador que proporcione un esquema y una variable de modelo. Un ejemplo de un marco donde han eliminado la necesidad del desarrollador para definir el esquema de datos es django: un desarrollador escribe sus modelos en el archivo models.py y lo deja en el marco para administrar el esquema. La primera razón que me viene a la mente de por qué lo hacen, dada mi experiencia con django, es la facilidad de uso. Quizás lo más importante es el principio DRY (no te repitas), no tienes que acordarte de actualizar el esquema cuando cambies el modelo. ¡Django lo hará por ti! Rails también administra el esquema de los datos para usted: un desarrollador no edita el esquema directamente, sino que lo modifica definiendo las migraciones que manipulan el esquema.
Una razón por la que podría entender que Mongoose separará el esquema y el modelo es casos en los que le gustaría construir un modelo a partir de dos esquemas. Tal escenario puede presentar más complejidad de la que vale la pena administrar: si tiene dos esquemas que son administrados por un modelo, ¿por qué no son un esquema?
Quizás la pregunta original sea más una reliquia del sistema de base de datos relacional tradicional. En World NoSQL/Mongo world, quizás el esquema sea un poco más flexible que MySQL/PostgreSQL, y por lo tanto, cambiar el esquema es una práctica más común.
En palabras sencillas,
Un modelo es un modelo de objetos de datos, como puedes encontrar en un pattern.It de diseño MVC define Estructura qué tipo de datos tiene que ser almacenado en una base de datos y lo tipo de relación que tienen los datos.
Un esquema es como un database schema
, la definición de lo que será almacenada en una base de datos.
- 1. ¿Por qué Spring Integration tiene varios esquemas XML y cuál debo usar?
- 2. ¿Por qué Mongoose agrega matrices en blanco?
- 3. Mongoose asincrónico por defecto
- 4. Modelos Django: ¿Por qué el nombre choca?
- 5. ¿Por qué TStringList tiene BeginUpdate y EndUpdate?
- 6. Uso de esquemas PostgreSQL múltiples con modelos Rails
- 7. mongoose vs mongodb (nodejs modules/extensions), ¿qué mejor? ¿y por qué?
- 8. ¿Por qué ReadProcessMemory tiene `lpNumberOfBytesRead`?
- 9. ¿Por qué Ruby tiene Numeric.new?
- 10. ¿Por qué MongoDB tiene colecciones
- 11. MongoDB via Mongoose JS - ¿Qué es findByID?
- 12. ¿Mongoose solo admite documentos incrustados en matrices?
- 13. Mongoose embedded document updating
- 14. ¿por qué jvm tiene muchos clasloaders? ¿por qué no uno?
- 15. Mongoose alternativa?
- 16. ¿Por qué DOM tiene ventana y uno mismo?
- 17. ¿Por qué java tiene los archivos cacerts y jssecacerts?
- 18. ¿Por qué el JDK tiene Math.random() y la clase Random?
- 19. ¿Por qué la biblioteca estándar tiene find y find_if?
- 20. ¿Por qué los esquemas de color vim difieren entre gvim y un terminal normal?
- 21. Node.js mongoose performance
- 22. ¿Qué opinas sobre Desarrollo de software impulsado por modelos?
- 23. ¿Por qué ArrayList tiene "implementa la Lista"?
- 24. ¿Para qué sirve el desarrollo impulsado por modelos?
- 25. Django: ¿Por qué algunos campos de modelos chocan entre sí?
- 26. ¿Por qué DotNetNuke tiene validación deshabilitada?
- 27. ¿Por qué C no tiene paquete privado?
- 28. ¿Por qué SerializationInfo no tiene métodos TryGetValue?
- 29. ¿Por qué ActionScript no tiene "genéricos"?
- 30. ¿Por qué stdarg.h tiene una macro «__va_size»?
En general, se recomienda no enviar enlaces desnudos como respuesta a las preguntas publicadas en SO, ya que el enlace puede dejar de funcionar (como en este caso). Al menos copie/pase y cite las secciones relevantes de los artículos a los que se vincula. – Behrang
hecho - todavía estaba en la memoria caché de Google, por lo que es relativamente simple –
Para el registro, el problema del método de documento incrustado se ha solucionado: https://github.com/LearnBoost/mongoose/issues/249#ref-commit-e18077a – Dakota