Как динамически построить оператор агрегирования Mongodb? - PullRequest
0 голосов
/ 28 февраля 2019

В следующей функции я пытаюсь динамически построить условие запроса mongo $or.PriceRanges принимается в качестве параметра функции.Я строю priceRanges следующим образом, чтобы построить оператор $or для моей проекции:

    let $or = [];

    for(let filter of priceRanges) {
        $or.push( { $gte: [ "$price", +filter.low ] }, { $lte: [ "$price", +filter.high ] })
    }

Массив $or теперь содержит следующие значения:

console.log('$or', $or)

    $or [ 
          { '$gte': [ '$price', 100 ] }, { '$lte': [ '$price', 200 ] },
          { '$gte': [ '$price', 200 ] }, { '$lte': [ '$price', 300 ] },
          { '$gte': [ '$price', 300 ] }, { '$lte': [ '$price', 400 ] } 
        ]

Здесь ясоздайте оператор проекта:

let $project = {
        name:1,
        producttype:1,
        brand:1,
        model:1,
        price:1,
        list_price:1,
        description:1,
        rating:1,
        sku:1,
        feature:1,
        image:1,
        images: 1,
        specifications:1,        
     };

Я добавляю к проекции условие $or:

$project.priceRange = {$or: $or};

Оператор $ or выглядит следующим образом:

{ '$or':
   [ { '$gte': [Array] },{ '$lte': [Array] },
 { '$gte': [Array] }, { '$lte': [Array] },
 { '$gte': [Array] }, { '$lte': [Array] } ] }

Я создаю массив моих операторов проекции:

aggregateArray.push({$project: $project});

console.log(aggregateArray) выглядит следующим образом:

aggregateArray [ { '$project':
 { name: 1,
   producttype: 1,
   brand: 1,
   model: 1,
   price: 1,
   list_price: 1,
   description: 1,
   rating: 1,
   sku: 1,
   feature: 1,
   image: 1,
   images: 1,
   specifications: 1,
   priceRange: [Object] } },
  { '$skip': 1 },
  { '$limit': 4 } ]

Я выполняю проекцию следующим образом:

let products = await Product.aggregate(aggregateArray);

При выполнении оператор $or не оказывает никакого влияния.Результат содержит случайные цены, а не указанные диапазоны.

1 Ответ

0 голосов
/ 28 февраля 2019

Проблема здесь в том, что методы push массива javascript принимают массив значений в качестве параметра, поэтому $or.push( { $gte: [ "$price", +filter.low ] }, { $lte: [ "$price", +filter.high ] }) выдвигает два отдельных условия фильтрации.Поэтому price, равный 50, также будет включен в ваш результат, поскольку он соответствует второму условию (ниже 200).Чтобы исправить это, вам нужно объединить эти пары, используя $ и , чтобы ваше окончательное условие фильтрации выглядело так:

var $or =  [ 
            { $and: [ { '$gte': [ '$price', 100 ] }, { '$lte': [ '$price', 200 ] } ] },
            { $and: [ { '$gte': [ '$price', 200 ] }, { '$lte': [ '$price', 300 ] } ] },
            { $and: [ { '$gte': [ '$price', 300 ] }, { '$lte': [ '$price', 400 ] } ] }
        ]

Тогда, если вам нужно это для фильтрации, его следует использовать с $ expr внутри $ match stage.

db.col.aggregate([
    {
        $match: { $expr: { $or: $or } }
    },
    // other aggregation stages
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...