MongoDB选择distinct和count

时间:2015-04-23 06:39:02

标签: mongodb

我有一个类似的产品系列:

products = [
  {
      "ref": "1",
      "facets": [
        { 
          "type":"category",
          "val":"kitchen" 
        },
        { 
          "type":"category",
          "val":"bedroom" 
        },
        { 
          "type":"material",
          "val":"wood" 
        }            

      ]
  },
  {
      "ref": "2",
      "facets": [
        { 
          "type":"category",
          "val":"kitchen" 
        },
        { 
          "type":"category",
          "val":"livingroom" 
        },
        { 
          "type":"material",
          "val":"plastic" 
        }            
      ]
  }
]

我想选择和统计具有该类别的不同类别和产品数量(请注意,产品可以包含多个类别)。这样的事情:

[
  {
    "category": "kitchen",
    "numberOfProducts": 2
  },
  {
    "category": "bedroom",
    "numberOfProducts": 1
  },
  {
    "category": "livingroom",
    "numberOfProducts": 1
  }
]

如果我能为每个不同的facet类型得到相同的结果会更好,就像那样:

[
  {
    "facetType": "category",
    "distinctValues":
          [
            {
              "val": "kitchen",
              "numberOfProducts": 2
            },
            {
              "val": "livingroom",
              "numberOfProducts": 1
            },
            {
              "val": "bedroom",
              "numberOfProducts": 1
            }
          ]
  },
  {
    "facetType": "material",
    "distinctValues":
          [
            {
              "val": "wood",
              "numberOfProducts": 1
            },
            {
              "val": "plastic",
              "numberOfProducts": 1
            }
          ]
  }
]    

我正在使用distinct,aggregate和mapReduce进行测试。但无法达到所需的效果。谁能告诉我好方法?

更新:

使用聚合,这可以为我提供产品具有的不同方面类别,但不包括值和不同值的计数:

db.products.aggregate([
    {$match:{'content.facets.type':'category'}}, 
    {$group:{ _id: '$content.facets.type'} }  
]).pretty();

1 个答案:

答案 0 :(得分:1)

以下聚合管道将为您提供所需的结果。在第一个管道步骤中,您需要对facets数组执行$unwind操作,以便对其进行解构以输出每个元素的文档。 $unwind阶段之后是$group个操作中的第一个,它按类别和类型对上一个流中的文档进行分组,并使用$ sum计算每个组中的产品数。然后,下一个管道阶段中的下一个$ group操作将使用$addToSet运算符创建保存聚合值的数组。最后的管道阶段是$project操作,然后通过修改现有字段来转换流中的文档:

var pipeline = [
    { "$unwind": "$facets" },
    {
        "$group": {
            "_id": {
                "facetType": "$facets.type",
                "value": "$facets.val"
            },
            "count": { "$sum": 1 }
        }
    },
    {
        "$group": {
            "_id": "$_id.facetType",
            "distinctValues": {
                "$addToSet": {
                    "val": "$_id.value",
                    "numberOfProducts": "$count"
                }
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "facetType": "$_id",
            "distinctValues": 1
        }
    }
];

db.product.aggregate(pipeline);

<强>输出

/* 0 */
{
    "result" : [ 
        {
            "distinctValues" : [ 
                {
                    "val" : "kitchen",
                    "numberOfProducts" : 2
                }, 
                {
                    "val" : "bedroom",
                    "numberOfProducts" : 1
                }, 
                {
                    "val" : "livingroom",
                    "numberOfProducts" : 1
                }
            ],
            "facetType" : "category"
        }, 
        {
            "distinctValues" : [ 
                {
                    "val" : "wood",
                    "numberOfProducts" : 1
                }, 
                {
                    "val" : "plastic",
                    "numberOfProducts" : 1
                }
            ],
            "facetType" : "material"
        }
    ],
    "ok" : 1
}