Условная фильтрация вложенного объекта в MongoDB - PullRequest
0 голосов
/ 16 сентября 2018

У меня проблема с поиском ключа вложенного объекта.

У меня есть объект критериев поиска, который может иметь или не иметь определенные поля, по которым я хотел бы искать.

Я решаю это, используя условные операторы для добавления к объекту «критерий соответствия», который передается в агрегатный оператор $ match. это работает хорошо, пока мне не нужно сопоставить что-то внутри вложенного объекта.

Вот пример структуры документа

{
        name: string,
        dates: {
            actived: Date,
            suspended: Date
        },
        address : [{
            street: string,
            city: string,
            state: string,
            zip: string
        }]

    };

Мой объект критериев заполняется через пользовательский интерфейс и передает JSON, который выглядит примерно так:

{
        "name": "",
        "state": ""
    }

И хотя я могу явно использовать «date.suspended» без проблем - при попытке добавить address.state к критериям поиска - появляется ошибка.

module.exports.search = function( criteria, callback ) 

        let matchCriteria = {
            "name": criteria.name,
            "dates.suspended": null
        };


        if ( criteria.state !== '' ) {
           // *** PROBLEM HAPPENS HERE *** //
            matchCriteria.address.state = criteria.state;
        }

        User.aggregate([
            { "$match": matchCriteria },
            { "$addFields": {...} },
            { "$project": {...} }
        ], callback );

    }

Я получаю сообщение об ошибке:

TypeError: Невозможно установить свойство 'state' из неопределенного

Я понимаю, что я указываю 'address.state', когда 'address' еще не существует, но мне неясно, каким будет мой синтаксис, безусловно, он не будет matchCriteria ['address.state'] или " matchCriteria.address.state "

Есть ли лучший способ сделать условную фильтрацию?

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Это должно это исправить:

matchCriteria['address.state'] = criteria.state;
0 голосов
/ 16 сентября 2018

Для поиска во вложенном объекте, вы должны использовать unwind

Запрос, который вам поможет:

// Для тестирования объявляем criteria как const

 let  criteria = {name : 'name', 'state' : 'state'};
 let addressMatch = {};
 let matchCriteria = {
            "name": criteria.name,
            "dates.suspended": null
        };


        if ( criteria.state) {

            addressMatch = { 'address.state' :  criteria.state };
        }

db.getCollection('user').aggregate([{
    $match :matchCriteria,
    },{$unwind:'$address'},
    {$match :  addressMatch}
    ])
0 голосов
/ 16 сентября 2018

Сначала проверьте адрес, а затем получите доступ к свойству, как показано:

if(matchCriteria['address']) {
 matchCriteria['address']['state'] = criteria['state'];
}
else {
//otherwise
}
...