【问题标题】:Find overall min and max values in aggregate group results with single query使用单个查询在聚合组结果中查找总体最小值和最大值
【发布时间】:2016-02-13 00:37:45
【问题描述】:

我的集合中存储了一个对象,如下所示:

[{ 
    "_id" : ObjectId("56bcbe570793be2e5025567e"),   
    "CarPlate" : "AB123CD", 
    "Brand" : "BMW", 
    "Version" : "316d", 
    "Description" : "BMW 316d", 
    "Prices" : [
        {
            "PriceType" : NumberInt(0), 
            "VatType" : NumberInt(0), 
            "Currency" : "EUR", 
            "Value" : 20100.0
        }, 
        {
            "PriceType" : NumberInt(3), 
            "VatType" : NumberInt(0), 
            "Currency" : "EUR", 
            "Value" : 23900.0
        }, 
        {
            "PriceType" : NumberInt(4), 
            "VatType" : null, 
            "Currency" : "EUR", 
            "Value" : 30950.0
        }
    ]
}, { 
    "_id" : ObjectId("56bcbe570793be2e5025567f”),   
    "CarPlate" : "AB123CE”, 
    "Brand" : "BMW", 
    "Version" : "318d", 
    "Description" : "BMW 318d", 
    "Prices" : [
        {
            "PriceType" : NumberInt(0), 
            "VatType" : NumberInt(0), 
            "Currency" : "EUR", 
            "Value" : 23900.0
        }, 
        {
            "PriceType" : NumberInt(3), 
            "VatType" : NumberInt(0), 
            "Currency" : "EUR", 
            "Value" : 23900.0
        }, 
        {
            "PriceType" : NumberInt(4), 
            "VatType" : null, 
            "Currency" : "EUR", 
            "Value" : 40250.0
        }
    ]
}]

我想使用单个查询检索 [整个集合] 的最低和最高价格值,其中 PriceType 等于 4。

我找到了一种方法,但运行两个不同的查询(基本上相同的查询,但排序不同)

db.Cars.aggregate(
  [
    {
      $unwind: '$Prices'
    },
    {
      $match: {
      'Prices.PriceType': 4
      }
    },
    {
      $group: {
        _id: '$CarPlate',
        valueMin: { $min: '$Prices.Value' },
        valueMax: { $max: '$Prices.Value' }
      }
    },
    {
      $sort: {
        valueMin: 1
      }
    },
    {
      $limit: 1
    }
  ]
);

有什么提示吗?

【问题讨论】:

  • 澄清您想为整个集合中的每个汽车/文档/对象找到最小值和最大值?或从整个集合中选择一分钟和一分钟
  • 致全集
  • 所以根据您的示例数据,您想要这样的结果吗? { min: 20100.0, max: 40250.0 }
  • 是的,没错。全系列最高价和最低价的一项记录

标签: mongodb mongodb-.net-driver


【解决方案1】:

这是你要找的东西吗:

> db.Cars.aggregate([
                    {
                       $unwind:"$Prices"
                    }, 
                    {
                       $match:{"Prices.PriceType":4}
                    }, 
                    {
                       $group:
                        {_id:"$CarPlate", 
                          max_price:{$max:"$Prices.Value"}, 
                          min_price:{$min:"$Prices.Value"}
                        }
                    }, 
                   {
                       $group:
                       {_id:null, 
                        max_value:{$max:"$max_price"}, 
                        min_value:{$min:"$min_price"}
                       }
                   }
                  ])

这将在整个集合中输出具有最小值和最大值的单个值。

【讨论】:

  • 看起来不错!谢谢,让我尝试将其转换为 c#,但在 shell 上运行它可以工作
  • 很好,很高兴它有帮助。
  • 您可以通过在 Price.PricesType 上添加索引并在 $unwind 之前添加另一个 $match 来优化此查询,以仅保留数组中至少有一个带有此 PriceType 的价格的文档。当然,在展开后仍然需要相同的 $match ,但这不会从索引中受益。这将使 $unwind + $match 更快,但这取决于您的数据集。如果 100% 的数据具有 PriceType=4,那将无济于事。
  • 不幸的是我所有的数据都有 PriceType =4
【解决方案2】:

对于所有知道如何将这样的查询转换为 c# 的人(再次感谢@ibininja),这里的 c# 代码:

this.carRepository
    .Collection
    .Aggregate()
    .Match(priceTypeFilder)
    .Unwind<Car, CarToPrice>(i => i.Prices)
    .Match(x => x.Prices.PriceType == PriceTypeEnum.Catalog)
    .Group(key =>  key.CarPlate ,
    g => new
    {
        _id = g.Key,
        MinPrice = g.Min(o => o.Prices.Value),
        MaxPrice = g.Max(o => o.Prices.Value)
    })
    .Group(key => key._id,
    g => new
    {
        _id = (string)null,
        MinPrice = g.Min(o => o.MinPrice),
        MaxPrice = g.Max(o => o.MaxPrice)
    })
    .SingleAsync();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 2013-10-26
    • 2016-01-31
    • 2012-09-16
    • 2017-08-18
    • 2015-04-12
    相关资源
    最近更新 更多