我有一个文档集合,每个文档都包含数组。我想要的输出是按特定标准过滤的展开数组元素。
我可以通过以下方式做到这一点:
db.collection.aggregate([
{
$unwind: "$myArrayField"
},
{
$match: {
"myArrayField.myCriteriaField": "myValue"
}
}
])
但是放松一切似乎很浪费,所以我这样做了
db.collection.aggregate([
{
$match: {
"myArrayField.myCriteriaField": "myValue"
}
},
{
$unwind: "$myArrayField"
},
{
$match: {
"myArrayField.myCriteriaField": "myValue"
}
}
])
要过滤出可行的候选文档,展开它们,然后再次过滤展开的元素,因为会有不匹配的元素。
或者,我也可以
db.collection.aggregate([
{
$project: {
myArrayField: {
$filter: {
input: "$myArrayField",
as: "element",
cond: { $eq: ["$$element.myCriteriaField", "myValue"] }
}
}
}
},
{
$unwind: "$myArrayField"
}
])
甚至
db.collection.aggregate([
{
$match: {
"myArrayField.myCriteriaField": "myValue"
}
},
{
$project: {
myArrayField: {
$filter: {
input: "$myArrayField",
as: "element",
cond: { $eq: ["$$element.myCriteriaField", "myValue"] }
}
}
}
},
{
$unwind: "$myArrayField"
}
])
哪一个最有效率?我对聚合的运行方式了解不够,无法知道它可能依赖哪些变量(集合大小、文档大小等)。
最后,比赛展开比赛看起来非常简单,但这样做也感觉不对,所以我想知道我是否错过了一些东西。
首先你应该在该字段上有一个索引。
那么你应该尽早限制结果,这意味着
$match
阶段应该首先出现。
剩下的更多的是口味问题。