基本的mongodb嵌套集搜索,只想检索单个值

时间:2015-04-10 16:06:26

标签: mongodb mongodb-query pymongo nosql

我刚开始使用基于文档的数据存储大约3-4个小时,我有一个基本问题,我想了解。

    {
      "_id": "5527e5ae06e55c02049bd114",
      "owner": "John Doe",
      "customers" : ["5527e3c806e55c01dad3a132", "5527e3c806e55c01dad3a133", "5527e3c806e55c01dad3a134"],
      "location" : [
        {
          "address": "Wall St",
          "location_id": "123123213",
          "vendor" : [
            {
              "name" : "hello 123",
              "price" : "3",
              "serial" : "000000009730978e"
            },
            {
              "name" : "hello abc",
              "price" : "3.5",
              "serial" : "0000000097308888"
            }
          ]
        },
        {
          "address" : "PCH 1",
          "location_id": "987987",
          "vendor" : [
            {
              "name" : "hello 456342",
              "price" : "4",
              "serial" : "000000009733452435"
            },
            {
              "name" : "hello sdfsdg",
              "price" : "4.5",
              "serial" : "0000000095243532453"
            }
          ]
        }
      ]
    }

那么如何找到location.serial.price?

db.test.find_one( {"location.location_id" : "123123213" , "location.vendor.serial" : "000000009730978e"  }  )

将返回整个对象,但我只对这些条件匹配的location.serial.price感兴趣。

非常感谢, 本

2 个答案:

答案 0 :(得分:1)

通常你会使用positional-operator($)来引用数组条目。但不幸的是,这个运算符有一个严重的限制:它不适用于嵌套数组。所以在这种情况下它没有帮助你。

你可以做的是使用一个聚合管道,unwind是两个数组,然后match是串口。

db.test.aggregate([
    // create a stream of location-documents
    { $unwind: "$location" },
    // filter the stream by location-id
    { $match: { "location.id" : "123123213" },
    // expand the remaining stream further to individual vendor-documents
    { $unwind: "$vendor" },
    // filter the stream by serial
    { $match: { "location.vendor.serial": "000000009730978e" } }
]);

请记住,聚合可能会变得很慢。它还具有每个聚合步骤16MB的限制。您可以使用allowDiskUse:true选项来避免此限制,但这会使速度更慢。因此,当您需要考虑大量数据和性能时,您可能需要重新考虑数据库架构。

答案 1 :(得分:0)

Mongodb aggregation在这里使用,下面的查询将满足您的标准

db.collectionName.aggregate({
    "$unwind": "$location"
},
{
    "$match": {
    "location.location_id": "123123213"
    }
},
{
    "$unwind": "$location.vendor"
},
{
    "$match": {
    "location.vendor.serial": "000000009730978e"
    }
},
{
    "$project": {
    "serial": "$location.vendor.serial",
    "price": "$location.vendor.price",
    "_id": 0
    }
}).pretty()