Используйте $ или с $ elemMatch и условие вне массива

1

Моя основная структура: у меня есть объект User с объектом сеанса, который содержит subjectId и почасовую цену.

User{
    defaultHourly: Number,
    subjects{
        [
            id: String,
            hourly: Number
        ]
    }
}    

Я использую elemMatch следующим образом:

query.elemMatch("subjects", {
                "id": { $in: subjects },
                "$or": [
                    { "hourly": { $eq: null } }, // this is my issue
                    {
                        "$and": [
                            { "hourly": { $ne: null } },
                            { "hourly": { $gte: price.low, $lte: price.high } }
                        ]
                    }
                ]
            });

первая часть elemMatch гарантирует, что объект, который я хочу, находится в массиве объектов. Затем я хочу фильтровать по цене. если пользователь имеет нулевое значение в почасовом поле, я хочу затем сравнить defaultHourly с price.low и price.high.

Проблема в том, что defaultHourly не является полем для объектов, но является полем родительского объекта, поэтому я не уверен, как получить к нему доступ.

Я хочу написать:

"$or": [
           { 
                "$and": [
                   { "hourly": { $eq: null } },
                   { "defaultHourly": { $gte: price.low, $lte: price.high } } //this doesnt work because default hourly is not a field.
                ]
           },
           {
               "$and": [
                   { "hourly": { $ne: null } },
                   { "hourly": { $gte: price.low, $lte: price.high } }
                ]
            }
       ]
 }); 

Как я могу сделать это многоуровневое сравнение?

Теги:
mongoose
mongodb-query

1 ответ

1
Лучший ответ

Вы пишете условие за пределами $elemMatch и помещаете $or на верхний уровень документа. Это позволяет использовать каждый "набор" условий:

User.find({
  "$or": [
     { 
       "defaultHourly": { "$gte": price.low, "$lte": price.high },
       "subjects": {
         "$elemMatch": { 
           "id": { "$in": subjects },
           "hourly": { "$eq": null }
         }
       }
     },
     {
       "subjects": {
         "$elemMatch": {
           "id": { "$in": subjects },
           "hourly": { "$gte": price.low, "$lte": price.high }
         }
       }
     }
  ] 
})

Также обратите внимание, что $ne не требуется, поскольку сравнение "range" фактически отрицает значение null поскольку оно просто не будет "больше" фактического числового значения.

Кроме того, обратите внимание, что все выражения запросов MongoDB уже являются условиями AND, такими как $gte и $lte в одном и том же свойстве. Поэтому, даже если это не требуется, $ne также можно записать в виде:

   "hourly": { "$gte": price.low, "$lte": price.high, "$ne": null }

Это устраняет необходимость в явном $and.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню