MongoDB:聚合管道中的$ mod运算符

时间:2016-05-15 16:55:08

标签: mongodb mongodb-query aggregation-framework nosql

我有一个包含3772个文档的restaurants集合,我正在尝试计算score数组的第一个元素中包含grades的文档总数。使用聚合框架的7的倍数。

查询:

db.restaurants.aggregate([
{$project: {remainder: {$mod: ["$grades.0.score", 7]},
            restaurant_id: 1,
            name: 1,
            grades: 1
            }
},
{$match: {remainder: {$eq: 0}}},
{$group: {_id: null, total: {$sum: 1}}}
])

但是,我收到的错误消息是由于在$mod管道阶段使用$project运算符引起的。错误消息如下:

  

$ mod仅支持数字类型,而不支持Array和NumberDouble

但是,$grades.0.score7都是整数,对吗?我应该更改什么才能使此查询按预期工作?

示例文档:

{
"_id" : ObjectId("57290430139a4a37132c9e93"),
"address" : {
    "building" : "469",
    "coord" : [
        -73.961704,
        40.662942
    ],
    "street" : "Flatbush Avenue",
    "zipcode" : "11225"
},
"borough" : "Brooklyn",
"cuisine" : "Hamburgers",
"grades" : [
    {
        "date" : ISODate("2014-12-30T00:00:00Z"),
        "grade" : "A",
        "score" : 8
    },
    {
        "date" : ISODate("2014-07-01T00:00:00Z"),
        "grade" : "B",
        "score" : 23
    },
    {
        "date" : ISODate("2013-04-30T00:00:00Z"),
        "grade" : "A",
        "score" : 12
    },
],
"name" : "Wendy'S",
"restaurant_id" : "30112340"
}

2 个答案:

答案 0 :(得分:1)

而不是$grades.0.score
$grades[0].score 在你的查询中。

以上是错误的。见下面正确的表格。由于您希望按第一个得分为7的倍数的等级进行过滤,因此您应该像这样开始聚合。

db.restaurants.aggregate([{$match: {"grades.0.score": {$mod: [7, 0]}}},{$group: {_id: null, total: {$sum: 1}}}])

我将grade.0.score更改为7并运行命令检查它是否正常工作,它似乎正常工作。

> db.restaurants.find().pretty();
{
        "_id" : 0,
        "address" : {
                "building" : "469",
                "coord" : [
                        -73.961704,
                        40.662942
                ],
                "street" : "Flatbush Avenue",
                "zipcode" : "11225"
        },
        "borough" : "Brooklyn",
        "cuisine" : "Hamburgers",
        "grades" : [
                {
                        "date" : ISODate("2014-12-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 7
                },
                {
                        "date" : ISODate("2014-07-01T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                },
                {
                        "date" : ISODate("2013-04-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                }
        ],
        "name" : "Wendy'S",
        "restaurant_id" : "30112340"

> db.restaurants.aggregate([{$match: {"grades.0.score": {$mod: [7, 0]}}},{$group:{_id:null,count:{$sum:1}}} ])    
{ "_id" : null, "count" : 1 }

答案 1 :(得分:0)

首先:为什么它不起作用?尝试:

    db.restaurants.aggregate([
    {$project: {
        score0: "$grades.0.score",
        restaurant_id: 1,
        name: 1
        }
    }
    ])

您将看到score0返回[0个元素],因此它会输出一个数组,因此会显示错误消息。

基于另一个问题Get first element in array and return using Aggregate? (Mongodb),以下是您问题的解决方案:

    db.restaurants.aggregate([
       {$unwind: "$grades"},
       {$group:{"_id":"$_id","grade0":{$first:"$grades"}}},
       {$project: {
          remainder: {$mod: ["$grade0.score", 7]},
          restaurant_id: 1,
          name: 1,
          grade0: 1,
          }
      },
      {$match: {remainder: {$eq: 0}}},
      {$group: {_id: null, total: {$sum: 1}}}
    ])