Os dois tipos de objetos parecem estar tão próximos um do outro que ter os dois parece redundante. Qual é o ponto de ter ambos os esquemas e modelos?
Os dois tipos de objetos parecem estar tão próximos um do outro que ter os dois parece redundante. Qual é o ponto de ter ambos os esquemas e modelos?
Respostas:
Freqüentemente, a maneira mais fácil de responder a esse tipo de pergunta é com um exemplo. Neste caso, alguém já fez isso por mim :)
Dê uma olhada aqui:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
EDITAR: A postagem original (conforme mencionado nos comentários) parece não existir mais, então estou reproduzindo-a abaixo. Se ele retornar ou se tiver apenas mudado, entre em contato.
Ele fornece uma descrição decente do uso de esquemas dentro de modelos no mongoose e por que você gostaria de fazer isso, e também mostra como enviar tarefas por meio do modelo enquanto o esquema trata da estrutura etc.
Postagem original:
Vamos começar com um exemplo simples de incorporação de um esquema dentro de um 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'});
Criei um novo TaskSchema
objeto com informações básicas que uma tarefa pode ter. Um atributo virtual Mongoose é configurado para combinar convenientemente o nome e a prioridade da Tarefa. Eu apenas especifiquei um getter aqui, mas os setters virtuais também são suportados.
Eu também defini um método de tarefa simples chamado isHighPriority
para demonstrar como os métodos funcionam com esta configuração.
Na ListSchema
definição, você notará como a chave de tarefas é configurada para conter uma série de TaskSchema
objetos. A chave de tarefa se tornará uma instância DocumentArray
que fornece métodos especiais para lidar com documentos Mongo embutidos.
Por enquanto, eu apenas passei o ListSchema
objeto para mongoose.model e deixei o TaskSchema de fora. Tecnicamente não é necessário transformar o TaskSchema
em um modelo formal, pois não o estaremos salvando em sua própria coleção. Posteriormente, mostrarei como isso não prejudica nada se você fizer isso e pode ajudar a organizar todos os seus modelos da mesma maneira, especialmente quando eles começam a se espalhar por vários arquivos.
Com a List
configuração do modelo, vamos adicionar algumas tarefas a ele e salvá-las no 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');
}
});
O atributo de tarefas na instância de nosso List
model ( simpleList
) funciona como um array JavaScript regular e podemos adicionar novas tarefas a ele usando push. O importante a notar é que as tarefas são adicionadas como objetos JavaScript regulares. É uma distinção sutil que pode não ser imediatamente intuitiva.
Você pode verificar no shell do Mongo se a nova lista e as tarefas foram salvas no 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" }
Agora podemos usar o ObjectId
para obter o Sample List
e iterar por meio de suas tarefas.
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());
});
});
Se você executar o último pedaço de código, receberá um erro dizendo que o documento incorporado não tem um método isHighPriority
. Na versão atual do Mongoose, você não pode acessar métodos em esquemas integrados diretamente. Há um tíquete aberto para consertá-lo e, depois de fazer a pergunta ao Mongoose Google Group, manimal45 postou uma solução útil para usar agora.
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));
});
});
Se você executar esse código, verá a seguinte saída na linha de comando.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Com essa solução alternativa em mente, vamos transformar o TaskSchema
em um modelo Mongoose.
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');
A TaskSchema
definição é a mesma de antes, então eu a deixei de fora. Depois de transformado em um modelo, ainda podemos acessar seu objeto Schema subjacente usando a notação de ponto.
Vamos criar uma nova lista e incorporar duas instâncias do modelo Task nela.
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 incorporando as instâncias do modelo Task na Lista, estamos chamando toObject
-as para converter seus dados em objetos JavaScript simples que o List.tasks
DocumentArray
está esperando. Quando você salva instâncias de modelo desta forma, seus documentos incorporados irão conter ObjectIds
.
O exemplo de código completo está disponível como uma essência . Esperançosamente, essas soluções alternativas ajudam a suavizar as coisas conforme o Mongoose continua a se desenvolver. Ainda sou muito novo no Mongoose e no MongoDB, então sinta-se à vontade para compartilhar melhores soluções e dicas nos comentários. Modelagem de dados feliz!
Schema é um objeto que define a estrutura de qualquer documento que será armazenado em sua coleção MongoDB; ele permite que você defina tipos e validadores para todos os seus itens de dados.
Modelo é um objeto que fornece acesso fácil a uma coleção nomeada, permitindo que você consulte a coleção e use o Schema para validar quaisquer documentos salvos nessa coleção. Ele é criado combinando um Schema, uma Connection e um nome de coleção.
Originalmente formulado por Valeri Karpov, MongoDB Blog
Não acho que a resposta aceita realmente responda à pergunta que foi feita. A resposta não explica por que o Mongoose decidiu exigir que um desenvolvedor forneça uma variável Schema e uma Model. Um exemplo de uma estrutura em que eles eliminaram a necessidade do desenvolvedorpara definir o esquema de dados é django - um desenvolvedor escreve seus modelos no arquivo models.py, e deixa para o framework gerenciar o esquema. A primeira razão que vem à mente para fazer isso, dada a minha experiência com django, é a facilidade de uso. Talvez o mais importante seja o princípio DRY (não se repita) - você não precisa se lembrar de atualizar o esquema quando alterar o modelo - o django fará isso por você! O Rails também gerencia o esquema dos dados para você - um desenvolvedor não edita o esquema diretamente, mas o altera definindo migrações que manipulam o esquema.
Um motivo pelo qual pude entender que o Mongoose separaria o esquema e o modelo são as instâncias em que você deseja construir um modelo a partir de dois esquemas. Tal cenário pode apresentar mais complexidade do que vale a pena gerenciar - se você tem dois esquemas que são gerenciados por um modelo, por que eles não são um esquema?
Talvez a pergunta original seja mais uma relíquia do sistema de banco de dados relacional tradicional. No mundo NoSQL / Mongo, talvez o esquema seja um pouco mais flexível do que o MySQL / PostgreSQL e, portanto, alterar o esquema é uma prática mais comum.
Para entender por quê? você tem que entender o que realmente é o Mongoose?
Bem, o mongoose é uma biblioteca de modelagem de dados de objeto para MongoDB e Node JS, fornecendo um nível mais alto de abstração. Portanto, é um pouco como o relacionamento entre Express e Node, então Express é uma camada de abstração sobre Node regular, enquanto Mongoose é uma camada de abstração sobre o driver MongoDB regular.
Uma biblioteca de modelagem de dados de objeto é apenas uma maneira de escrevermos código Javascript que irá interagir com um banco de dados. Portanto, poderíamos apenas usar um driver MongoDB regular para acessar nosso banco de dados, funcionaria perfeitamente.
Mas, em vez disso, usamos o Mongoose porque ele nos dá muito mais funcionalidade pronta para uso, permitindo o desenvolvimento mais rápido e simples de nossos aplicativos.
Portanto, alguns dos recursos que o Mongoose nos fornece esquemas para modelar nossos dados e relacionamento, validação de dados fácil, uma API de consulta simples, middleware e muito mais.
No Mongoose, um esquema é onde modelamos nossos dados, onde descrevemos a estrutura dos dados, valores padrão e validação, então pegamos esse esquema e criamos um modelo a partir dele, um modelo é basicamente um invólucro em torno do esquema, o que nos permite realmente interagir com o banco de dados para criar, excluir, atualizar e ler documentos.
Vamos criar um modelo a partir de um esquema.
const tourSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
},
rating: {
type: Number,
default: 4.5,
},
price: {
type: Number,
required: [true, 'A tour must have a price'],
},
});
//tour model
const Tour = mongoose.model('Tour', tourSchema);
De acordo com a convenção, a primeira letra de um nome de modelo deve ser maiúscula.
Vamos criar uma instância do nosso modelo que criamos usando mangusto e esquema. também, interaja com nosso banco de dados.
const testTour = new Tour({ // instance of our model
name: 'The Forest Hiker',
rating: 4.7,
price: 497,
});
// saving testTour document into database
testTour
.save()
.then((doc) => {
console.log(doc);
})
.catch((err) => {
console.log(err);
});
Portanto, ter tanto o schama quanto o modle mangusto torna nossa vida mais fácil.