2016-01-30 3 views
0

j'ai une structure de données qui ressemble plus ou moins comme ceci:Nesting et l'interrogation des documents avec MongoDB

var city = { 
    name: String, 
    mayor: Person, 
    citizens: [Person] 
}; 

Je pense que mon cas d'utilisation est assez bon pour l'utilisation de MongoDB, mais j'ai quelques questions. Le modèle ci-dessus a été implémenté avec mongoose, et j'utilise sub documents pour imbriquer des personnes à l'intérieur de City.Obviously le tableau de citoyens pourrait devenir assez long, et c'est pourquoi MongoDB semble être un bon choix.

Est-ce un moyen efficace de structurer mes données? Je me demandais si Mongo devra faire une sorte de rejoindre chaque fois que je veux sélectionner une ville, avec tout de ses citoyens (ou une grande partie d'entre eux). Cela irait évidemment à l'encontre de l'objectif de l'utilisation d'une base de documents.

De même, lorsque vous êtes dans le terminal mongo, j'essaie quelque chose comme db.cities.find({name:'Berlin'}).mayor Je n'obtiens aucun résultat. Quand j'essaie db.cities.find({name:'Berlin'}), il montre la ville, et il montre aussi un identifiant d'objet pour le maire mais pas toutes les propriétés du maire/Personne.

Alors, comment puis-je interroger avec sous-documents et est-ce une bonne façon de travailler?

Répondre

0

Je recommanderais votre schéma comme suit avec Populate. Il n'y a pas joins dans MongoDB mais parfois nous voulons toujours des références à des documents dans d'autres collections. C'est là la population entre en jeu.

var personSchema = Schema({ 
    _id  : Number, 
    name : String, 
}); 

var Person = mongoose.model('Person', personSchema); 

var citySchema = Schema{ 
    name: String, 
    mayor: { type: Schema.Types.ObjectId, ref: 'Person' }, 
    citizens: [{ type: Schema.Types.ObjectId, ref: 'Person' }] 
}; 

var City = mongoose.model('City', citySchema); 

Pour interroger la ville comme Berlin par

City.find({name: 'Berlin'}) 
    .populate('mayor') 
    .populate('citizens') 
    .exec(...) 

Le document relatif mayor et citizens sera récupéré à partir de DB.

Si vous préoccupez il y a trop de citizens dans la ville pour faire la city trop grande avec populate la personne dans le city, une autre option est

var personSchema = Schema({ 
    _id  : Number, 
    name : String, 
    cityId : { type: Schema.Types.ObjectId, ref: 'City' } 
}); 

var Person = mongoose.model('Person', personSchema); 

var citySchema = Schema{ 
    name: String, 
    mayor: { type: Schema.Types.ObjectId, ref: 'Person' } 
}; 

var City = mongoose.model('City', citySchema); 

Pour interroger la ville Berlin avec aggregation, voici la exemples de codes.

City.find({name: 'Berlin'}) 
    .populate('mayor') 
    .exec(function(err, city) { 
     Person.aggregate([ 
      {$group: {cityId: city._id, citizens: {$push: '$name'}}} 
      // ... 
     ], function(err, result) { 
      //... 
});