J'ai 2 documents différents que je souhaite joindre en fonction d'un attribut spécifique. Sur le premier document, je veux utiliser $ group pour regrouper les documents en fonction d'un attribut, puis utiliser le résultat pour joindre un deuxième document.
Mon premier document spotmodel a cette structure: p>
{
"_id" : ObjectId("5c16d339e6cbea23a0393b47"),
"description" : "Area A",
"streets" : [
{
"_id" : ObjectId("5c16d3e6e6cbea23a0393b4b"),
"name" : "Waterloo",
"codes":[
{
"code": "AD01"
},
{
"code": "AD02"
}
]
},
{
"_id" : ObjectId("5c16d536e6cbea23a0393b51"),
"name" : "Bristol"
}
]
}
Mon deuxième document areamodel a la structure suivante:
db.spotmodel.aggregate([
{
$group: {
_id: "$streetId",
codes: {
$push: {
code: "$code",
}
}
}
},
{$lookup: {
from: "db.areamodel",
localField: "streets._id",
foreignField: "_id",
as: "details"
}},
{$match:{details:{$ne:[]}}}
])
Je souhaite regrouper mon spotmodel document basé sur le streetId et utilisez cette requête groupée pour joindre le document areamodel à tout moment streetId correspond à rues ._id
Jusqu'à présent, j'ai la requête suivante:
{
"_id" : ObjectId("5c16d339e6cbea23a0393b47"),
"description" : "Area A",
"streets" : [
{
"_id" : ObjectId("5c16d3e6e6cbea23a0393b4b"),
"name" : "Waterloo"
},
{
"_id" : ObjectId("5c16d536e6cbea23a0393b51"),
"name" : "Bristol"
}
]
}
,
{
"_id" : ObjectId("5c16d339e6cbea23a0393b47"),
"description" : "Area B",
"streets" : [
{
"_id" : ObjectId("5c16d3e6e6cbea23a0393b2a"),
"name" : "Park Av."
},
{
"_id" : ObjectId("5c16d536e6cbea23a0393b2b"),
"name" : "Nelson St."
}
]
}
mais ce code me donne un tableau vide [] code> mais le résultat que j'attends est quelque chose comme ceci:
{
"_id" : ObjectId("5c17724498ea721018ba9d59"),
"code" : "AD01",
"streetId" : ObjectId("5c16d3e6e6cbea23a0393b4b")
},
{
"_id" : ObjectId("5c17724498ea721018ba9d60"),
"code" : "AD02",
"streetId" : ObjectId("5c16d3e6e6cbea23a0393b4b")
}
// other documents with same or different streetID
Où est mon erreur?
3 Réponses :
Vous pouvez utiliser ci-dessous agrégation
db.areamodel.aggregate([
{ "$unwind": "$streets" },
{ "$lookup": {
"from": "spotmodel",
"localField": "streets._id",
"foreignField": "streetId",
"as": "codes"
}},
{ "$addFields": { "streets.codes": "$codes.code" }},
{ "$group": {
"_id": "$_id",
"streets": { "$push": "$streets" },
"description": { "$first": "$description" }
}}
])
La recherche est terriblement lente dans mongodb pour les grands ensembles de données. Essayez de dénormaliser vos documents.
// schema on nodejs via mongoose:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var flatSchema = new Schema({
_id: ObjectId,
rentType: Number,
price: Number,
thumbnail: String,
address: {
country: String,
city: String,
street: String,
district: Number
// ... more fields
}
// ... some more fields
}, { collection: 'flats'});
module.exports = mongoose.model('Flat', flatSchema);
-----
/ e.g. let's define request
var rules = [{'address.city': '1'}, {price: {$gte: 200}}];
// and here are the grouping request:
Flat.aggregate([
{ $match: {$and: rules } },
{
$project: {
_id: 0, // let's remove bson id's from request's result
price: 1, // we need this field
district: '$address.district' // and let's turn the nested field into usual field (usual renaming)
}
},
{
$group: {
_id: '$district', // grouping key - group by field district
minPrice: { $min: '$price'}, // we need some stats for each group (for each district)
maxPrice: { $max: '$price'},
flatsCount: { $sum: 1 }
}
}
], {}, callback);
First of all â itâs not possible to group by nested field, e.g. âaddress.districtâ, thats why we workarounded this by fieldâs renaming in $project.