лучший способ ограничить свойства поля в совокупном вызове - PullRequest
0 голосов
/ 27 апреля 2018

Итак, я пытаюсь выполнить вызов aggregate в MongoDB для поиска коллекции, но в то же время ограничить объем данных, которые я получаю из другой коллекции. Вот моя попытка такого рода работ:

getFamilyStats: function (req, res) {
    Families
        .aggregate([
            { $match: { 'centralPath': req.body.centralPath }},
            { $lookup: {
                from: 'models',
                localField: 'centralPath',
                foreignField: 'centralPath',
                as: 'models'
            }},
            { $unwind: '$models'},
            { $project: {
                'models.openTimes.user': 1,
                '_id': 1,
                'centralPath': 1,
                'totalFamilies': 1,
                'unusedFamilies': 1,
                'oversizedFamilies': 1,
                'inPlaceFamilies': 1,
                'families': 1
            }}
            ]
        ).exec(function (err, response){
            var result = {
                status: 200,
                message: response
            };
            if (err){
                result.status = 500;
                result.message = err;
            } else if (!response){
                result.status = 404;
                result.message = err;
            }
            res.status(result.status).json(result.message);
        });
},

То, что работает довольно хорошо, это то, что я могу использовать lookup для «объединения» данных из другой коллекции, в данном случае называемой моделями. Как только я unwind это, это в значительной степени похоже на то, что я хочу, за исключением того, что меня интересует только одно поле из этого свойства: models.openTimes и в данном конкретном случае фактически только одно свойство этого поля user. Я пытался использовать project, чтобы ограничить большую часть данных, которые я передаю из моделей, но это вынуждает меня указывать все остальные поля следующим образом:

_id: 1,
centralPath: 1....

Это не идеально, если моя коллекция пополняется новыми свойствами. Я ищу способ ограничить данные из models только этим одним полем / одним свойством, но получить все поля из коллекции families.

Идеи?

Пример данных для семей:

{
    "_id" : ObjectId("5ae08c75d132ac4442520672"),
    "centralPath" : "some path",
    "totalFamilies" : 0,
    "unusedFamilies" : 0,
    "oversizedFamilies" : 0,
    "inPlaceFamilies" : 0,
    "families" : [],
    "__v" : 0
}

Пример данных для моделей:

{
    "_id" : ObjectId("5ae08c74d132ac4442520638"),
    "centralPath" : "some path",
    "openTimes" : [ 
        {
            "value" : 8123,
            "user" : "ks",
            "createdOn" : ISODate("2018-04-25T14:11:00.853Z"),
            "_id" : ObjectId("5ae08c74d132ac444252063a")
        }
    ],
    "synchTimes" : [ 
        {
            "value" : 208649,
            "user" : "ks",
            "createdOn" : ISODate("2018-04-25T16:42:42.933Z"),
            "_id" : ObjectId("5ae0b0028c2e3b192a3e9dc5")
        }
    ],
    "modelSizes" : [ 
        {
            "value" : 21483520,
            "user" : "ks",
            "createdOn" : ISODate("2018-04-25T14:11:00.787Z"),
            "_id" : ObjectId("5ae08c74d132ac4442520639")
        }
    ],
    "__v" : 0
}

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Начиная с MongoDB v3.6, вы можете ограничить поля, возвращаемые $ lookup напрямую:

db.families.aggregate([
    { $match: { 'centralPath': 'some path' } },
    { $lookup: {
        from: 'models',
        let: { centralPath: '$centralPath' }, // remember the value of the "centralPath" field
        pipeline: [
            { $match: { $expr: { $eq: [ '$centralPath',  '$$centralPath' ] } } }, // this performs the "join"
            { $project: { _id: 0, 'openTimes.user': 1 } } // only retrieve the "openTimes.user" field
        ],
        as: 'models'
    }},
    { $unwind: '$models'},
]);
0 голосов
/ 17 мая 2018

Вы можете попробовать агрегацию ниже в версии 3.4 и выше.

$addFields для возврата единственного поля из объединенной коллекции при сохранении существующих полей и $project с исключением для удаления данных объединенной коллекции.

Заменить этап проекта на addFields и этап проекта.

Families.aggregate([
 existing stages,
  {"$addFields":{
    "user":"$models.openTimes.user"
  }},
  {"$project":{"models":0}}
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...