按子文档过滤子文档

时间:2015-05-07 20:36:26

标签: node.js mongodb mongoose

想象一下,你有以下猫鼬模式:

mongoose.model('Team', mongoose.Schema(
{
 players : [{ 
    trikots : [{
        isNew : Boolean,
        color : String
    }]
 }]
})

我想查询我的数据以获得符合以下内容的所有团队

  • 有trikots {isNew:true,color:red}
  • 只选择有trikots的玩家{isNew:true,color:red}

我开始使用$ elemMatch作为子子文档,但他们仍然是假的玩家。我必须使用aggregate()吗?怎么样?

1 个答案:

答案 0 :(得分:1)

是的, aggregation framework 可以实现这一目标。您的聚合管道将由$match运算符组成,该运算符将成为初始阶段。这将按指定的条件筛选集合中的文档。下一个管道步骤将是两个阵列players和嵌套players.trikots上的几个$uniwnd运算符。在$uniwnd之后,您需要另一个$match,然后将解构后的数组文档过滤到所需的条件,这将成为您的最终解决方案。

让我们通过将以上架构的几个文档插入mongo shell中的团队集合来证明这一点:

db.team.insert([
{
    "players" : [ 
        {
            "trikots" : [ 
                {
                    "isNew" : true,
                    "color" : "red"
                }, 
                {
                    "isNew" : true,
                    "color" : "blue"
                }
            ]
        }, 
        {
            "trikots" : [ 
                {
                    "isNew" : false,
                    "color" : "red"
                }, 
                {
                    "isNew" : true,
                    "color" : "green"
                }
            ]
        }
    ]
},
{
    "players" : [ 
        {
            "trikots" : [ 
                {
                    "isNew" : false,
                    "color" : "red"
                }, 
                {
                    "isNew" : false,
                    "color" : "blue"
                }
            ]
        }
    ]
}
])

然后可以按如下方式实现上述聚合管道:

var pipeline = [
    {
        "$match": {
            "players.trikots.isNew": true,
            "players.trikots.color": "red"
        }
    },
    {
        "$unwind": "$players"
    },
    {
        "$unwind": "$players.trikots"
    },
    {
        "$match": {
            "players.trikots.isNew": true,
            "players.trikots.color": "red"
        }
    }
];
db.team.aggregate(pipeline);

<强>输出:

/* 1 */
{
    "result" : [ 
        {
            "_id" : ObjectId("554bce9a2ba32ccf7f139bae"),
            "players" : {
                "trikots" : {
                    "isNew" : true,
                    "color" : "red"
                }
            }
        }
    ],
    "ok" : 1
}

你的猫鼬聚合类似:

Team.aggregate(pipeline).exec(callback);

或使用Mongoose aggregation pipeline builder 进行流畅的通话:

Team.aggregate()
    .match({"players.trikots.isNew": true,"players.trikots.color": "red"})
    .unwind("players")
    .unwind("players.trikots")
    .match({"players.trikots.isNew": true,"players.trikots.color": "red"}) 
    .exec(callback);