MongoDB/Mongoose 如何 return 通过 _id 嵌套子文档
MongoDB/Mongoose how to return a nested subdocument by _id
MongoDB这里是新手
我有一个 'client' 文档,如下所示:
{
name: "myClient",
products: [{
name: "myProduct1",
environments: [{
name: "myEnvironment1",
changeLogs: [
{ "some": "fields21" },
{ "some": "fields22" }
]
},
{
name: "myEnvironment2",
changeLogs: [
{ "some": "fields11" },
{ "some": "fields12" }
]
}
]
},
{
name: "myProduct2",
environments: [{
name: "myEnv1",
changeLogs: [
{ "some": "fields1" },
{ "some": "fields2" }
]
},
{
name: "myEnv1",
changeLogs: [
{ "some": "fields3" },
{ "some": "fields4" }
]
}
]
}]
}
所以一个客户有很多products
,有很多environments
,有很多changeLogs
。我正在寻找 return 给定环境的 changeLogs
列表,只有 environment._id
可以继续。
我可以使用 _id
:
找到正确的 client
文档
db.clients.find({'products.environments._id': ObjectId("5a1bf4b410842200043d56ff")})
但这 return 是整个 client
文档。我想要的是 return 只是环境中的 changeLogs
数组 _id: ObjectId("5a1bf4b410842200043d56ff")
假设我有第一个product
的第一个environment
的_id
,我想要的输出如下:
[
{ "some": "fields21" },
{ "some": "fields22" }
]
您建议我使用什么查询来实现此目的?
非常感谢您的帮助。到目前为止的文档只是令人困惑,但我相信我最终会到达那里!
这里的思路是$unwind
the products array so that its environments can be fed as input to $filter
after a $match
上_id
。
(假设环境 _id 为 1)
db.collection.aggregate([
{
$unwind: "$products"
},
{
$match: {
"products.environments._id": 1
}
},
{
$project: {
"logsArray": {
$filter: {
input: "$products.environments",
as: "env",
cond: {
$eq: [
"$$env._id",
1
]
}
}
}
}
},
{
$unwind: "$logsArray"
}
])
O/P 应该是这样的:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"logsArray": {
"changeLogs": [
{
"some": "fields21"
},
{
"some": "fields22"
}
],
"id": 1,
"name": "myEnvironment1"
}
}
]
注意: 注意 logsArray
的最后阶段 $unwind
,我认为这只是漂亮的输出。否则没有它,结果也是可以接受的(如果你同意,可以删除它)。
这只是进行聚合查询的另一种方式。这样就得到了想要的结果。
请注意,我使用的是您提供的示例文档中 "environments" 的 "name" 字段。 "name" 可以根据需要替换为 "id"。
var ENV = "myEnvironment1";
db.env.aggregate( [
{ $match: {
{ $unwind: "$products" },
{ $unwind: "$products.environments" },
{ $match: { "products.environments.name": ENV} },
{ $project: { _id: 0, changeLogs: "$products.environments.changeLogs" } },
] )
结果:
{ "changeLogs" : [ { "some" : "fields21" }, { "some" : "fields22" } ] }
如果变量ENV
的值改变了,那么结果也会相应;例如:ENV = "myEnv1";
{ "changeLogs" : [ { "some" : "fields1" }, { "some" : "fields2" } ] }
{ "changeLogs" : [ { "some" : "fields3" }, { "some" : "fields4" } ] }
db.clients.aggregate([
{
$unwind: "$products"
},
{
$unwind: "$products.environments"
},
{
$match: { "products.environments._id": ObjectId("5a1bf4b410842200043fffff") }
},
{
$project: { _id: 0, changeLogs: "$products.environments.changeLogs" }
}
]).pretty()
结果:
{
"changeLogs": [
{ "some": "fields21" },
{ "some": "fields22" }
]
}
对于那些发现代码令人困惑的人,我发现一次只添加一个聚合方法非常有用,查看结果,然后将下一个方法添加到管道中。管道完成后,我还尝试删除中间步骤,看看是否可以用更少的管道获得相同的结果。
MongoDB这里是新手
我有一个 'client' 文档,如下所示:
{
name: "myClient",
products: [{
name: "myProduct1",
environments: [{
name: "myEnvironment1",
changeLogs: [
{ "some": "fields21" },
{ "some": "fields22" }
]
},
{
name: "myEnvironment2",
changeLogs: [
{ "some": "fields11" },
{ "some": "fields12" }
]
}
]
},
{
name: "myProduct2",
environments: [{
name: "myEnv1",
changeLogs: [
{ "some": "fields1" },
{ "some": "fields2" }
]
},
{
name: "myEnv1",
changeLogs: [
{ "some": "fields3" },
{ "some": "fields4" }
]
}
]
}]
}
所以一个客户有很多products
,有很多environments
,有很多changeLogs
。我正在寻找 return 给定环境的 changeLogs
列表,只有 environment._id
可以继续。
我可以使用 _id
:
client
文档
db.clients.find({'products.environments._id': ObjectId("5a1bf4b410842200043d56ff")})
但这 return 是整个 client
文档。我想要的是 return 只是环境中的 changeLogs
数组 _id: ObjectId("5a1bf4b410842200043d56ff")
假设我有第一个product
的第一个environment
的_id
,我想要的输出如下:
[
{ "some": "fields21" },
{ "some": "fields22" }
]
您建议我使用什么查询来实现此目的?
非常感谢您的帮助。到目前为止的文档只是令人困惑,但我相信我最终会到达那里!
这里的思路是$unwind
the products array so that its environments can be fed as input to $filter
after a $match
上_id
。
(假设环境 _id 为 1)
db.collection.aggregate([
{
$unwind: "$products"
},
{
$match: {
"products.environments._id": 1
}
},
{
$project: {
"logsArray": {
$filter: {
input: "$products.environments",
as: "env",
cond: {
$eq: [
"$$env._id",
1
]
}
}
}
}
},
{
$unwind: "$logsArray"
}
])
O/P 应该是这样的:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"logsArray": {
"changeLogs": [
{
"some": "fields21"
},
{
"some": "fields22"
}
],
"id": 1,
"name": "myEnvironment1"
}
}
]
注意: 注意 logsArray
的最后阶段 $unwind
,我认为这只是漂亮的输出。否则没有它,结果也是可以接受的(如果你同意,可以删除它)。
这只是进行聚合查询的另一种方式。这样就得到了想要的结果。
请注意,我使用的是您提供的示例文档中 "environments" 的 "name" 字段。 "name" 可以根据需要替换为 "id"。
var ENV = "myEnvironment1";
db.env.aggregate( [
{ $match: {
{ $unwind: "$products" },
{ $unwind: "$products.environments" },
{ $match: { "products.environments.name": ENV} },
{ $project: { _id: 0, changeLogs: "$products.environments.changeLogs" } },
] )
结果:
{ "changeLogs" : [ { "some" : "fields21" }, { "some" : "fields22" } ] }
如果变量ENV
的值改变了,那么结果也会相应;例如:ENV = "myEnv1";
{ "changeLogs" : [ { "some" : "fields1" }, { "some" : "fields2" } ] }
{ "changeLogs" : [ { "some" : "fields3" }, { "some" : "fields4" } ] }
db.clients.aggregate([
{
$unwind: "$products"
},
{
$unwind: "$products.environments"
},
{
$match: { "products.environments._id": ObjectId("5a1bf4b410842200043fffff") }
},
{
$project: { _id: 0, changeLogs: "$products.environments.changeLogs" }
}
]).pretty()
结果:
{
"changeLogs": [
{ "some": "fields21" },
{ "some": "fields22" }
]
}
对于那些发现代码令人困惑的人,我发现一次只添加一个聚合方法非常有用,查看结果,然后将下一个方法添加到管道中。管道完成后,我还尝试删除中间步骤,看看是否可以用更少的管道获得相同的结果。