如何动态构建Mongodb聚合语句?

时间:2019-02-28 17:06:30

标签: javascript mongodb mongodb-query

在以下功能中,我试图动态构建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 :(得分:1)

这里的问题是javascript数组的push方法将值数组作为参数,因此$or.push( { $gte: [ "$price", +filter.low ] }, { $lte: [ "$price", +filter.high ] })推送了两个单独的过滤条件。因此,等于price的{​​{1}}也将包含在您的结果中,因为它匹配第二个条件(低于50)。要解决此问题,您需要使用$and合并这些对,以便最终的过滤条件应如下所示:

200

然后,如果您需要过滤它,则应在$expr阶段与$match一起使用。

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