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

basic mongodb nested sets search, only want to retrieve single value

我刚开始使用基于文档的数据存储大约 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"  }  )

会 returns 整个对象,但我只对 location.serial.price 这些条件匹配的地方感兴趣。

非常感谢, 本

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

您可以改为使用 unwinds both arrays and then 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 选项避免该限制,但这会使它变得更慢。因此,当您有大量数据并且性能是一个问题时,您可能需要重新考虑您的数据库模式。

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