好的,我对Mongo很新,而且我已经卡住了。
Db具有以下结构(当然非常简化):
{
{
"_id" : ObjectId("57fdfbc12dc30a46507044ec"),
"keyterms" : [
{
"score" : "2",
"value" : "AA",
},
{
"score" : "2",
"value" : "AA",
},
{
"score" : "4",
"value" : "BB",
},
{
"score" : "3",
"value" : "CC",
}
]
},
{
"_id" : ObjectId("57fdfbc12dc30a46507044ef"),
"keyterms" : [
...
有一些物体。每个对象都有一个数组" keywords"。每个阵列条目,都有分数和价值。虽然有一些重复(不是真的,因为在真正的数据库中,关键字条目有更多的字段,但是关于价值和分数,它们是重复的。)
现在我需要一个查询,
所以我希望得到类似的结果
// for Object 57fdfbc12dc30a46507044ec
"keyterms"; [
{
"score" : "4",
"value" : "BB",
"count" : 1
},
{
"score" : "3",
"value" : "CC",
"count" : 1
}
{
"score" : "2",
"value" : "AA",
"count" : 2
}
]
在SQL中我会写这样的东西
select
score, value, count(*) as count
from
all_keywords_table_or_some_join
group by
value
order by
score
但遗憾的是,它不是SQL。
在Mongo,我设法写了这个:
db.getCollection('tests').aggregate([
{$match: {'_id': ObjectId('57fdfbc12dc30a46507044ec')}},
{$unwind: "$keyterms"},
{$sort: {"keyterms.score": -1}},
{$group: {
'_id': "$_id",
'keyterms': {$push: "$keyterms"}
}},
{$project: {
'keyterms.score': 1,
'keyterms.value': 1
}}
])
但缺少一些东西:按关键字对关键字进行分组。我无法摆脱这种感觉,这根本就是错误的做法。如何选择关键字数组并继续使用,并在此处使用聚合函数 - 这很容易。
BTW我读过这篇文章 (Mongo aggregate nested array) 但不幸的是,我不能为我的例子弄清楚......
答案 0 :(得分:3)
您需要一个聚合管道,在您 $unwind
数组之后,您可以按数组的value
和score
键对展平的文档进行分组,聚合使用 $sum
累加器运算符进行计数,并使用 $first
运算符保留主文档的_id
。
然后,前面的管道应该通过_id
键对上一个管道中的文档进行分组,以便保留原始架构并使用 $push
<重新创建keyterms
数组/ strong>运营商。
以下演示尝试解释上述聚合操作:
db.tests.aggregate([
{ "$match": { "_id": ObjectId("57fdfbc12dc30a46507044ec") } },
{ "$unwind": "$keyterms" },
{
"$group": {
"_id": {
"value": "$keyterms.value",
"score": "$keyterms.score"
},
"doc_id": { "$first": "$_id" },
"count": { "$sum": 1 }
}
},
{ "$sort": {"_id.score": -1 } },
{
"$group": {
"_id": "$doc_id",
"keyterms": {
"$push": {
"value": "$_id.value",
"score": "$_id.score",
"count": "$count"
}
}
}
}
])
示例输出
{
"_id" : ObjectId("57fdfbc12dc30a46507044ec"),
"keyterms" : [
{
"value" : "BB",
"score" : "4",
"count" : 1
},
{
"value" : "CC",
"score" : "3",
"count" : 1
},
{
"value" : "AA",
"score" : "2",
"count" : 2
}
]
}
<强>演示强>
答案 1 :(得分:1)
与此同时,我自己解决了这个问题:
aggregate([
{$match: {'_id': ObjectId('57fdfbc12dc30a46507044ec')}},
{$unwind: "$keyterms"},
{$sort: {"keyterms.score": -1}},
{$group: {
'_id': "$keyterms.value",
'keyterms': {$push: "$keyterms"},
'escore': {$first: "$keyterms.score"},
'evalue': {$first: "$keyterms.value"}
}},
{$limit: 15},
{$project: {
"score": "$escore",
"value": "$evalue",
"count": {$size: "$keyterms"}
}}
])