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

8

我是一名Mongoose/Mongo的新手:

我的数据

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

{ "__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'),但奇怪的是它返回了整个inventories数组。如果可能的话,我希望保持链式查询格式,因为我觉得它更易读。

我的理想查询

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

显然它并不能起作用,但它可以让你了解我试图做什么。
2个回答

11
使用 $ 位置操作符,您可以获得结果。然而,如果您在 vehicles 数组中有多个元素,则所有元素都将返回在结果中,因为在投影中只能使用一个位置操作符,并且您正在处理 2 个数组(一个在另一个内部)。
我建议您查看 聚合框架,因为您将获得更多灵活性。这是一个在 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
}

我喜欢这种方法,你的方式很好。 - Ogbonna Vitalis

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接