Mongoose查询:查找数组中的元素

mongoose/ Mongo noob在这里:

我的数据

这里是我的简化数据,每个用户都有自己的文档

{ "__v" : 1, "_id" : ObjectId( "53440e94c02b3cae81eb0065" ), "email" : "test@test.com", "firstName" : "testFirstName", "inventories" : [ { "_id" : "active", "tags" : [ "inventory", "active", "vehicles" ], "title" : "activeInventory", "vehicles" : [ { "_id" : ObjectId( "53440e94c02b3cae81eb0069" ), "tags" : [ "vehicle" ], "details" : [ { "_id" : ObjectId( "53440e94c02b3cae81eb0066" ), "year" : 2007, "transmission" : "Manual", "price" : 1000, "model" : "Firecar", "mileageReading" : 50000, "make" : "Bentley", "interiorColor" : "blue", "history" : "CarProof", "exteriorColor" : "blue", "driveTrain" : "SWD", "description" : "test vehicle", "cylinders" : 4, "mileageType" : "kms" } ] } ] }, { "title" : "soldInventory", "_id" : "sold", "vehicles" : [], "tags" : [ "inventory", "sold", "vehicles" ] }, { "title" : "deletedInventory", "_id" : "deleted", "vehicles" : [], "tags" : [ "inventory", "sold", "vehicles" ] } ] } 

如您所见,每个用户都有一个inventories属性,该属性是包含3个库存(activeInventory,soldInventory和deletedInventory)

我的查询

鉴于用户的电子邮件车辆ID,我想我的查询通过查找用户的activeInventory并返回与ID匹配的车辆。 这是我到目前为止:

 user = api.mongodb.userModel; ObjectId = require('mongoose').Types.ObjectId; return user .findOne({email : params.username}) .select('inventories') .find({'title': 'activeInventory'}) //also tried //.where('title') //.equals('activeInventory') .exec(function(err, result){ console.log(err); console.log(result); }); 

有了这个,结果出来了一个空arrays。 我也尝试.find('inventories.title': 'activeInventory') ,这奇怪地返回整个库存数组。 如果可能的话,我想保持链式查询格式,因为我发现它更可读。

我的理想质疑

 return user .findOne({email : params.username}) .select('inventories') .where('title') .equals('activeInventory') .select('vehicles') .id(vehicleID) .exec(cb) 

显然这不起作用,但它可以给你一个想法,我想要做什么。

使用$位置运算符可以得到结果。 但是,如果在vehicles数组中有多个元素,则所有这些元素都将返回到结果中,因为在投影中只能使用一个位置运算符,而您正在使用两个数组(一个在另一个内)。

我build议你看看aggregation framework ,因为你会获得更多的灵活性。 以下是在shell中运行的问题的示例查询。 我不熟悉mongoose,但我想这仍然可以帮助你,你可以翻译它:

 db.collection.aggregate([ // Get only the documents where "email" equals "test@test.com" -- REPLACE with params.username {"$match" : {email : "test@test.com"}}, // Unwind the "inventories" array {"$unwind" : "$inventories"}, // Get only elements where "inventories.title" equals "activeInventory" {"$match" : {"inventories.title":"activeInventory"}}, // Unwind the "vehicles" array {"$unwind" : "$inventories.vehicles"}, // Filter by vehicle ID -- REPLACE with vehicleID {"$match" : {"inventories.vehicles._id":ObjectId("53440e94c02b3cae81eb0069")}}, // Tidy up the output {"$project" : {_id:0, vehicle:"$inventories.vehicles"}} ]) 

这是你会得到的输出:

 { "result" : [ { "vehicle" : { "_id" : ObjectId("53440e94c02b3cae81eb0069"), "tags" : [ "vehicle" ], "details" : [ { "_id" : ObjectId("53440e94c02b3cae81eb0066"), "year" : 2007, "transmission" : "Manual", "price" : 1000, "model" : "Firecar", "mileageReading" : 50000, "make" : "Bentley", "interiorColor" : "blue", "history" : "CarProof", "exteriorColor" : "blue", "driveTrain" : "SWD", "description" : "test vehicle", "cylinders" : 4, "mileageType" : "kms" } ] } } ], "ok" : 1 } 

获取链接查询格式…我不知道如何parsing它,但是,你正在寻找的是投影,你应该看看http://docs.mongodb.org/manual/reference/operator/projection/

它可能看起来像这样:

 user.findOne({email: params.username}, {'inventories.title': {$elemMatch: "activeInventory", 'invertories.vehicle.id': $elemMatch: params.vehicleId}, function(err, result) { console.log(err); console.log(result); })