db.test.aggregate([
{ "$unwind": "$Data" },
{ "$sort" : { "Data.cost" : -1 } },
{ "$group":{
"_id":"$Data.name",
"Data":{ "$push": "$Data" }
}}
])
我解雇了上面的查询。它给我的结果如下:
{
"result":[{
"_id" : "abc"
"Data" : [
{
"uid" : "1...A",
"name" : "abc",
"city" : "Paris",
"description" : {
"things" : [
{
"fruit" : {
"fruit_name" : "apple",
"fruit_rate" : "4 USD"
},
"flower" : {
"flower_name" : "rose",
"flower_rate" : "2 USD"
}
}
]
},
"cost" : "6 USD"
},
{
"uid" : "1...B",
"name" : "abc",
"city" : "Paris",
"description" : {
"things" : [
{
"fruit" : {
"fruit_name" : "cherry",
"fruit_rate" : "3 USD"
},
"flower" : {
"flower_name" : "orchid",
"flower_rate" : "2 USD"
}
}
]
},
"cost" : "5 USD"
}
]
}]
}
但我不想要这样的结果。如果" name" 相同,我想合并两个数据的" description" 数组。 如下所述:
{
"result":[{
"_id" : "abc"
"Data" : [
{
"uid" : "1...A",
"name" : "abc",
"city" : "Paris",
"description" : {
"things" : [
{
"fruit" : {
"fruit_name" : "apple",
"fruit_rate" : "4 USD"
},
"flower" : {
"flower_name" : "rose",
"flower_rate" : "2 USD"
}
}
]
},
"description" : {
"things" : [
{
"fruit" : {
"fruit_name" : "cherry",
"fruit_rate" : "3 USD"
},
"flower" : {
"flower_name" : "orchid",
"flower_rate" : "2 USD"
}
}
]
},
"cost" : "6 USD"
}
]
}]
}
有可能得到这样的结果吗?我在查询中需要做哪些更改?
谢谢。
答案 0 :(得分:1)
您构建所需结果的方式根本不可能。这样做的原因是你基本上打破了Hash Table或字典/关联数组背后的原则(无论哪个术语更适合你),因为你不能有超过一个键值名。
如果您想要同名的多个键,那么这些键必须包含在一个数组中,这与您拥有的结构类型以及结果中的结构非常相似。除了对数组元素进行排序,然后将它们组合回一个数组之外,该结果并没有真正做任何事情。
所以在这里给你一些空间,因为你只需要复制并粘贴来表示你想要的结果,并且你真的想要某种形式的合并的内部元素,你可以总是做这样的事情:
db.test.aggregate([
{ "$unwind": "$Data" },
{ "$unwind": "$Data.description.things" },
{ "$group": {
"_id": "$Data.name",
"city": { "$first": "$Data.city" },
"things": { "$addToSet": "$Data.description.things" }
}}
])
产生结果:
{
"_id" : "abc",
"city" : "Paris",
"things" : [
{
"fruit" : {
"fruit_name" : "cherry",
"fruit_rate" : "3 USD"
},
"flower" : {
"flower_name" : "orchid",
"flower_rate" : "2 USD"
}
},
{
"fruit" : {
"fruit_name" : "apple",
"fruit_rate" : "4 USD"
},
"flower" : {
"flower_name" : "rose",
"flower_rate" : "2 USD"
}
}
]
}
因此,在对一个公共元素进行分组并添加一些额外字段时,内部“事物”现在被“推”到一个单个数组中。
如果你真的想要甚至更多“合并”的东西,甚至可能避免删除重复的“set”项目,那么你可以用这样的语句进一步重塑:
db.test.aggregate([
{ "$unwind": "$Data" },
{ "$unwind": "$Data.description.things" },
{ "$project": {
"name": "$Data.name",
"city": "$Data.city",
"things": "$Data.description.things",
"type": { "$literal": [ "flower", "fruit" ] }
}},
{ "$unwind": "$type" },
{ "$group": {
"_id": "$name",
"city": { "$first": "$city" },
"things": { "$push": { "$cond": [
{ "$eq": [ "$type", "flower" ] },
{
"type": "$type",
"name": "$things.flower.flower_name",
"rate": "$things.flower.flower_rate"
},
{
"type": "$type",
"name": "$things.fruit.fruit_name",
"rate": "$things.fruit.fruit_rate"
},
]}}
}}
])
结果如下:
{
"_id" : "abc",
"city" : "Paris",
"things" : [
{
"type" : "flower",
"name" : "rose",
"rate" : "2 USD"
},
{
"type" : "fruit",
"name" : "apple",
"rate" : "4 USD"
},
{
"type" : "flower",
"name" : "orchid",
"rate" : "2 USD"
},
{
"type" : "fruit",
"name" : "cherry",
"rate" : "3 USD"
}
]
}
这甚至可能表明原始数据首先如何更好地构建。当然,如果你想做一些像“找到'樱桃'或'鲜花'或'水果'的总价值”的东西,你肯定会需要重新塑造这样的形状或者不论那种类型。
因此,您构建结果的方式是不可能的,违反了上述规则。在我提出的表格中,有几种方法可以做到。
PS :我故意远离您的 $sort
表示,好像它在您的初始示例中“对您有用”,不要指望这可用于更广泛的示例,因为您的值是字符串而不是数字。简而言之,这意味着"10 USD"
实际上小于 "4 USD"
,因为字符串在词汇上进行词汇比较。即:4
大于 1
,这是比较完成的顺序。
因此,通过拆分字段并使用数字类型来更改它们,如:
{
"type" : "fruit",
"name" : "cherry",
"rate" : 3,
"currency": "USD"
}
如果需要,你甚至可以过滤“货币”。
P.P.S :$literal运算符是可用于MongoDB 2.6及更高版本的构造。在以前的版本中,该运算符不可用,您可以改为编码:
"type": { "$cond": [ 1, [ "flower", "fruit" ], 0 ] }
与$cond
(或甚至true
值)返回的false
值相同的事情是“字面上”声明的,所以你放在那里的内容实际上会被生成。在这种情况下,它是一种向投影添加“数组”的方法,这是为了匹配“类型”。
您可能会在网上找到使用 $const
的网址,但我并不特别相信,虽然它确实存在,但并不是为了这个目的因此没有正式记录。