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