按子文档过滤子文档

想象一下,你有以下mongoose模式:

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

我想查询我的数据以获得所有与以下匹配的团队

  • 有trikots {isNew:true,color:red}
  • 只有select玩家,有trikots {isNew:true,color:red}

我开始使用$ elemMatch子子文档,但他们仍然是错误的球员。 我必须使用aggregate()吗? 如何?

是的,这在聚合框架下是可以实现的。 你的聚合pipe道将包含一个$match操作符,它将成为初始阶段。 这将按照指定的标准过滤集合中的文档。 接下来的pipe道步骤是在arrays, players和嵌套players.trikots上的几个$uniwnd运算符。 在$uniwnd ,您将需要另一个$match ,然后将解构的数组文档过滤到所需的标准,这将成为您的最终解决scheme。

让我们通过在mongoshell中插入一组具有上述模式的文档来展示这一点:

 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" } ] } ] } ]) 

上面的聚合stream水线可以实现如下:

 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 } 

您的mongoose聚合将是相似的:

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

或者使用Mongoose 聚合pipe道生成器进行stream畅的调用:

 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);