MongoDB 选择不同的和计数

标签 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
  }
]

如果我能为每个不同的方面类型获得相同的结果,那就更好了,比如:

[
  {
    "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();

最佳答案

以下聚合管道将为您提供所需的结果。在第一个流水线步骤中,您需要执行 $unwind facets 数组上的操作,以便它被解构为每个元素输出一个文档。 $unwind之后阶段是第一个$group按类别和类型对前一个流中的文档进行分组的操作,并使用 $sum 计算每组中的产品数量。下一个管道阶段中的下一个 $group 操作然后使用 $addToSet 创建保存聚合值的数组。运算符(operator)。最后的管道阶段是 $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
}

关于MongoDB 选择不同的和计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29815560/

相关文章:

node.js - E11000 mongodb mongoose 中的重复键错误索引

机器上的 MongoDB 或 MongoDB Atlas

mongodb - mongod 主进程被 KILL 信号杀死

mongodb - 如何仅填充子文档数组中的第一个元素

node.js - 云9+mongodb+nodejs

MongoDB 文本搜索和排序依据

java - 从java连接到mongodb时如何防止登录控制台?

javascript - 如何导出对数据库连接的引用?

mongodb - 如何使用mongodb scala驱动程序在insertOne之后返回mongodb ObjectId _id

node.js - MongoDB/ Mongoose :Getting incorrect distance with geoNear method using geoJSON