Mongoose Query:查找数组中的元素

时间:2014-04-08 15:32:04

标签: arrays node.js mongodb 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);
    });

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

我理想的查询

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

显然它不起作用,但它可以让你知道我想要做什么。

2 个答案:

答案 0 :(得分:6)

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

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

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
}

答案 1 :(得分:3)

获取链接查询格式...我不知道如何解析它但是,你要搜索的是投影,你应该看看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);
})