Соедините 2 документа на MongoDB с $ group и $ lookup для вложенного свойства - PullRequest
0 голосов
/ 06 января 2019

У меня есть 2 разных документа, к которым я хочу присоединиться на основе определенного атрибута. В первом документе я хочу использовать $ group для группировки документов на основе атрибута, а затем использовать результат для соединения со вторым документом.

Мой первый документ spotmodel имеет такую ​​структуру:

{
"_id" : ObjectId("5c17724498ea721018ba9d59"),
"code" : "AD01",
"streetId" : ObjectId("5c16d3e6e6cbea23a0393b4b")
},
{
"_id" : ObjectId("5c17724498ea721018ba9d60"),
"code" : "AD02",
"streetId" : ObjectId("5c16d3e6e6cbea23a0393b4b")
}
// other documents with same or different streetID

Мой второй документ areamodel имеет следующую структуру:

{
"_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."
    }   
    ]
}

Я хочу сгруппировать документ spotmodel на основе streetId и использовать этот сгруппированный запрос для присоединения к документу areamodel в любое время streetId совпадения streets._id

Пока у меня есть следующий запрос:

db.spotmodel.aggregate([
{
$group: {
  _id: "$streetId",
  codes: {
    $push: {
      code: "$code",
    }
  }
}
},
{$lookup: {
     from: "db.areamodel",
     localField: "streets._id",
     foreignField: "_id",
     as: "details"
   }},
 {$match:{details:{$ne:[]}}}
 ])

но этот код дает мне пустой массив [], но результат, который я ожидаю, выглядит примерно так:

{
"_id" : ObjectId("5c16d339e6cbea23a0393b47"),
"description" : "Area A",
"streets" : [
    {
    "_id" : ObjectId("5c16d3e6e6cbea23a0393b4b"),
    "name" : "Waterloo",
    "codes":[
        {
        "code": "AD01"
        },
        {
        "code": "AD02"
        }
    ]
    },
    {
    "_id" : ObjectId("5c16d536e6cbea23a0393b51"),
    "name" : "Bristol"
    }   
    ]
}

Где моя ошибка?

Ответы [ 3 ]

0 голосов
/ 06 января 2019

Поиск очень медленный в mongodb для больших наборов данных. Попробуйте денормализовать ваши документы.

0 голосов
/ 07 января 2019
// 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 голосов
/ 06 января 2019

Вы можете использовать ниже aggregation

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" }
  }}
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...