Mongodb-使用聚合框架将多个字段分组

Mongodb-使用聚合框架将多个字段分组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一些文件 {name:'apple',type:'fruit',color:'red'} {名称:“香蕉”,类型:“水果”,颜色:“黄色”} {名称:“橙色”,类型:“水果”,颜色:“橙色”} {名称:“茄子”,类型:“蔬菜”,颜色:“紫色”} {名称:'brocoli',类型:'vege',颜色:'green'} {名称:'rose',类型:'flower',颜色:'red'} {名称:'cauli',类型:'vege',颜色:'white'} {名称:'potato',类型:'vege'

我有一些文件

{name:'apple',type:'fruit',color:'red'}
{名称:“香蕉”,类型:“水果”,颜色:“黄色”}
{名称:“橙色”,类型:“水果”,颜色:“橙色”}
{名称:“茄子”,类型:“蔬菜”,颜色:“紫色”}
{名称:'brocoli',类型:'vege',颜色:'green'}
{名称:'rose',类型:'flower',颜色:'red'}
{名称:'cauli',类型:'vege',颜色:'white'}
{名称:'potato',类型:'vege',颜色:'brown'}
{名称:“洋葱”,类型:“蔬菜”,颜色:“白色”}
{名称:“草莓”,类型:“水果”,颜色:“红色”}
{名称:“腰果”,类型:“坚果”,颜色:''
{名称:'almond',类型:'nut',颜色:'''
{名称:'lemon',类型:'vege',颜色:'yellow'}
{名称:“番茄”,类型:“蔬菜”,颜色:“红色”}
{名称:“番茄”,类型:“水果”,颜色:“红色”}
{名称:'fig',类型:'FROUT',颜色:'pink'}
{名称:'油桃',类型:'水果',颜色:'粉红'}
我想把它们分成下面这样的字母表

{
_id:'a',
名称:[“苹果”、“杏仁”],
类型:[],
颜色:[]
}
{
_id:'b',
名称:[“香蕉”、“花椰菜”],
类型:[],
颜色:[“棕色”]
}
...
{
_id:'f',
名称:['fig'],
类型:[“水果”、“花”],
颜色:['']
}
...
{
_id:'n',
名称:[‘油桃’],
类型:[“螺母”],
颜色:['']
}
...
{
_id:'p',
名称:[“土豆”],
类型:[''],
颜色:[“粉色”、“紫色”]
}
...
结果可以保存到另一个集合中。因此,我可以在新创建的集合中发出一个查询:
find({u id:'a'})
返回名称、类型和颜色,以字母“a”开头

我考虑过使用
$group

$group:{
_id:$substr:['$name',0,1],
名称:{$addToSet:'$name'},
}
然后是另一个命令

$group:{
_id:$substr:['$type',0,1],
名称:{$addToSet:'$type'},
}

$group:{
_id:$substr:['$color',0,1],
名称:{$addToSet:'$color'},
}
但我被困在如何将这三者统一起来,保存到一个新的集合中。或者聚合框架不适合这种数据摘要

在一个现实世界的例子中,例如一个电子商务网站,首页显示如下内容:“目前我们在
111
品牌的
231
类别下有
135636
产品”。当然,这些数字应该缓存在某个地方(内存或其他集合中),因为每次运行
$group
都需要大量资源?对于这些情况,最佳的模式/设计是什么


抱歉,我的问题有点“混乱”。

使用聚合时,您应该使用一些复杂的聚合查询。首先使用
substr
找出所有
name
首字母,然后创建所有
name,使用
键入和颜色
数组使用检查给定名称是否以开头用于删除重复的空参数,最后是用于在新集合中写入文档

检查此聚合查询:

    db.collection.aggregate({
    "$project": {
        "firstName": {
            "$substr": ["$name", 0, 1]
        },
        "name": 1,
        "type": 1,
        "color": 1
    }
}, {
    "$group": {
        "_id": null,
        "allName": {
            "$push": "$name"
        },
        "allType": {
            "$push": "$type"
        },
        "allColor": {
            "$push": "$color"
        },
        "allfirstName": {
            "$push": "$firstName"
        }
    }
}, {
    "$unwind": "$allfirstName"
}, {
    "$group": {
        "_id": "$allfirstName",
        "allType": {
            "$first": "$allType"
        },
        "allName": {
            "$first": "$allName"
        },
        "allColor": {
            "$first": "$allColor"
        }
    }
}, {
    "$project": {
        "type": {
            "$setDifference": [{
                    "$map": {
                        "input": "$allType",
                        "as": "type",
                        "in": {
                            "$cond": {
                                "if": {
                                    "$eq": [{
                                        "$substr": ["$$type", 0, 1]
                                    }, "$_id"]
                                },
                                "then": "$$type",
                                "else": ""
                            }
                        }
                    }
                },
                [""]
            ]
        },
        "color": {
            "$setDifference": [{
                    "$map": {
                        "input": "$allColor",
                        "as": "color",
                        "in": {
                            "$cond": {
                                "if": {
                                    "$eq": [{
                                        "$substr": ["$$color", 0, 1]
                                    }, "$_id"]
                                },
                                "then": "$$color",
                                "else": ""
                            }
                        }
                    }
                },
                [""]
            ]
        },
        "name": {
            "$setDifference": [{
                    "$map": {
                        "input": "$allName",
                        "as": "name",
                        "in": {
                            "$cond": {
                                "if": {
                                    "$eq": [{
                                        "$substr": ["$$name", 0, 1]
                                    }, "$_id"]
                                },
                                "then": "$$name",
                                "else": ""
                            }
                        }
                    }
                },
                [""]
            ]
        }
    }
}, {
    "$sort": {
        "_id": 1
    }
}, {
    "$out": "newCollection"
})

因为这里有多个数组,关键是将它们“合并”到一个数组中,以便进行最简单的处理

聚合框架的操作符在这里工作得很好,还可以转换元素,以便从数据中的每个单词中获得“第一个字母”:

db.alpha.aggregate([
{“$project”:{
“名单”:{
“$map”:{
“输入”:[“A”、“B”、“C”],
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el”,“A”]},
{ 
“type”:{“$literal”:“name”},
“值”:“$name”,
“alpha”:{“$substr”:[“$name”,0,1]}
},
{“$cond”:[
{“$eq”:[“$$el”,“B”]},
{
“类型”:{“$literal”:“类型”},
“值”:“$type”,
“alpha”:{“$substr”:[“$type”,0,1]}
},
{
“type”:{“$literal”:“color”},
“值”:“$color”,
“alpha”:{“$substr”:[“$color”,0,1]}
}
]}
]
}
}
}
}},
{“$unwind”:“$list”},
{“$match”:{“list.alpha”:{“$ne”:“}}},
{“$组”:{
“_id”:“$list.alpha”,
“名单”:{
$addToSet:“$list”
}
}},
{“$project”:{
“姓名”:{
“$setDifference”:[
{“$map”:{
“输入”:“$list”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.type”,“name”]},
“$$el.value”,
假的
]
}
}},
[错误]
]
},
“类型”:{
“$setDifference”:[
{“$map”:{
“输入”:“$list”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.type”,“type”]},
“$$el.value”,
假的
]
}
}},
[错误]
]
},
“颜色”:{
“$setDifference”:[
{“$map”:{
“输入”:“$list”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.type”,“color”]},
“$$el.value”,
假的
]
}
}},
[错误]
]
}
}},
{“$sort”:{“\u id”:1}
])
如果您在“阶段”中查看数据,那么在转换过程中发生的事情就很有意义了

第一阶段将所有字段“映射”到每个文档的单个数组中,因此所有文档现在看起来如下所示:

{
“_id”:ObjectId(“55df0652c9064ef625d7f36e”),
“名单”:[
{
“类型”:“名称”,
“价值”:“油桃”,
“alpha”:“n”
},
{
“类型”:“类型”,
“价值”:“水果”,
“阿尔法”: