【问题标题】:How do I dynamically build a Mongodb aggregation statement?如何动态构建MongoDB聚合语句?
【发布时间】:2019-02-28 17:06:30
【问题描述】:

在下面的函数中,我试图动态构建一个 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 语句似乎没有任何效果。结果包含随机价格,而不是指定的范围。

【问题讨论】:

    标签: javascript mongodb mongodb-query


    【解决方案1】:

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

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

    如果你需要它来过滤它应该在$match 阶段内使用$expr

    db.col.aggregate([
        {
            $match: { $expr: { $or: $or } }
        },
        // other aggregation stages
    ])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-27
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多