MongoDB新手在这里。
我有一个看起来像这样的“客户”文件:
{
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
。我希望返回给定环境的changeLogs
列表,仅继续执行environment._id
。
仅使用此client
,我就能找到正确的_id
文档:
db.clients.find({'products.environments._id': ObjectId("5a1bf4b410842200043d56ff")})
但这将返回整个client
文档。我想要的是使用changeLogs
_id: ObjectId("5a1bf4b410842200043d56ff")
数组
假设我拥有第一个_id
的第一个environment
的{{1}},我想要的输出如下:
product
您会建议我使用哪种查询来实现这一目标?
在此先感谢您的帮助。到目前为止,这些文档只是令人困惑,但我相信我最终会到达那里!
答案 0 :(得分:1)
这里的想法是$unwind
个产品数组,以便可以将其环境作为对_id
上的$filter
之后的$match
的输入。
(假设环境_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"
}
}
]
注意:请注意$unwind
的最后一个阶段logsArray
,我认为这是相当不错的结果。否则,如果没有它,结果也是可以接受的(如果您同意,可以将其删除)。
答案 1 :(得分:1)
这只是进行聚合查询的另一种方法。这样可以达到预期的效果。
注意,我使用的是您提供的示例文档中“环境”的“名称”字段。可以根据需要用“ 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" } ] }
答案 2 :(得分:0)
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" }
]
}
对于那些发现代码令人困惑的人,我发现一次只添加一个聚合方法,查看结果,然后在管道中添加下一个方法非常有用。管道完成后,我还尝试删除一些中间步骤,以查看是否可以通过减少管道次数获得相同的结果。