我尝试编写一个查询,该查询返回值keyword4
在我的集合中出现的字段label
{
"_id" : ObjectId("54071d4312bf9ee0d67f7cf8"),
"id" : "2",
"list" : [
{
"id" : 60,
"label" : "keyword3",
"pos" : 1
},
{
"id" : 89,
"label" : "keyword4",
"pos" : 2
},
{
"id" : 49,
"label" : "keyword4",
"pos" : 3
}
]
},
{
"_id" : ObjectId("5407sfkjsvnsvree9ee0d67f7cf8"),
"id" : "3",
"list" : [
{
"id" : 60,
"label" : "keyword3",
"pos" : 1
},
{
"id" : 89,
"label" : "keyword4",
"pos" : 2
},
{
"id" : 49,
"label" : "keyword4",
"pos" : 3
}
]
},
...
感谢。
答案 0 :(得分:2)
您在这里谈论的是“汇总结果”,因此您基本上使用aggregation framework。
这些步骤基本上是匹配包含所需值的文档,将数组内容仅过滤到那些匹配项,然后计算该字段值的出现次数。这里的主要运算符是$match
,它接受.find()
确实的查询参数,$unwind
允许您使用数组的元素,$group
执行实际的“聚合“,或者确实是你的元素的”计数“:
db.collection.aggregate([
// Match the documents to reduce what you are processing
{ "$match": { "list.label": "keyword4" } },
// Unwind the array to de-normalize or "un-join"
{ "$unwind": "$list" },
// Match again to "filter" the array content
{ "$match": { "list.label": "keyword4" } },
// Group your final results
{ "$group": {
"_id": "$list.label",
"count": { "$sum": 1 }
}}
])
这里的$sum
运算符将“求和”它作为参数提供的值。在这种情况下,您可以提供1
的基本值,以表示每个匹配事件的递增计数。
此外,这里存在“两个”$match
阶段的原因是因为MongoDB的工作方式以及它们分开的事情。第一阶段的目的是匹配满足条件的“文件”。这基本上与.find()
的结果相同,因为您匹配文档而不是数组的子文档。该陈述仅说明“包含”符合条件的元素。
第二阶段在$unwind
之后“处理”处理,现在集合中的其余文档显示为对数组中存在的每个元素进行“复制”,因此该数组元素为no - 一个数组,但是数组内容中的单个字段或“子文档”。
现在作为单独的文档,第二个$match
将“过滤”任何不符合条件的元素。所以现在只有“list.label”值匹配指定的值。您不希望省略第一个$match
,因为这意味着在集合中的每个文档上处理$unwind
,无论数组元素是否包含匹配项。这意味着你没有通过处理不可能计入结果的事情来做“不必要”的工作。
为了更好地理解和介绍使用聚合框架,文档中的SQL to aggregation mapping page值得关注,至少对于一些常见示例,如果您习惯于SQL表单,则更直接。
通常熟悉一般aggregation operators并了解其功能也是一个好主意。这是一个有用的工具,基本上是一般查询的对应物。非常值得学习,并且使用得很好。