1
votes

Joindre 2 documents sur MongoDB avec $ group et $ lookup sur la propriété imbriquée

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?


0 commentaires

3 Réponses :


1
votes

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" }
  }}
])


0 commentaires

0
votes

La recherche est terriblement lente dans mongodb pour les grands ensembles de données. Essayez de dénormaliser vos documents.


0 commentaires

0
votes
// 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.

0 commentaires