MongoDB:在第三级嵌入文档中查找匹配的元素



我是MongoDB的新手。我有一个典型的用例。这是我的单文档JSON结构。

{
"category":"cat_1",
"_id": "id1",
"levels":[
{
"id":"l1",
"orders":[
{
"id":"o1",
"screens":[
{
"id":"l1o1s1",
"name":"screen1"
},
{
"id": "l1o1s2",
"name": "screen2"
}
]
},
{
"id": "o2",
"screens": [
{
"id": "l1o2s1",
"name": "screen3"
},
{
"id": "l1o2s2",
"name": "screen4"
}
]
}
]
},
{
"id": "l2",
"orders": [
{
"id": "o1",
"screens": [
{
"id": "l2o1s1",
"name": "screen5"
},
{
"id": "l2o1s2",
"name": "screen6"
}
]
},
{
"id": "o2",
"screens": [
{
"id": "l2o2s1",
"name": "screen7"
},
{
"id": "l2o2s2",
"name": "screen8"
}
]
}
]
}
]
}

在这里,我只想获得给定屏幕ID的数据。例如,如果["l1o1s1","l1o2s2","l2o1s1","l2o2s1"]是我应该在文档中找到的屏幕ID列表,然后我想要下面的结果(它应该返回只在输入中给出的屏幕id(

{
"category":"cat_1",
"_id": "id1",
"levels":[
{
"id":"l1",
"orders":[
{
"id":"o1",
"screens":[
{
"id":"l1o1s1",
"name":"screen1"
}
]
},
{
"id": "o2",
"screens": [
{
"id": "l1o2s2",
"name": "screen4"
}
]
}
]
},
{
"id": "l2",
"orders": [
{
"id": "o1",
"screens": [
{
"id": "l2o1s1",
"name": "screen5"
},
]
},
{
"id": "o2",
"screens": [
{
"id": "l2o2s1",
"name": "screen7"
}
]
}
]
}
]
}

屏幕的输入不需要仅在单个文档中。它可能也存在于其他类别中。那么它应该只返回具有提到的屏幕id的文档。

有这样检索数据的想法吗?

正如@alex-blex所建议的,您的模式不支持这种查询,但如果您仍然想实现您的结果,您可以尝试使用聚合管道,但可能效率不高。

您可以尝试以下聚合管道:

db.collection.aggregate([
{
"$match": {
"levels.orders.screens.id": {
$in: [
"l1o1s1",
"l1o2s2",
"l2o1s1",
"l2o2s1"
]
}
}
},
{
"$unwind": "$levels"
},
{
"$unwind": "$levels.orders"
},
{
"$unwind": "$levels.orders.screens"
},
{
"$match": {
"levels.orders.screens.id": {
$in: [
"l1o1s1",
"l1o2s2",
"l2o1s1",
"l2o2s1"
]
}
}
},
{
"$replaceRoot": {
"newRoot": {
_id: "$_id",
"category": "$category",
"levelId": "$levels.id",
"orderId": "$levels.orders.id",
"screens": "$levels.orders.screens"
}
}
},
{
$group: {
_id: {
_id: "$_id",
"levelId": "$levelId",
"orderId": "$orderId",

},
"category": {
$first: "$category"
},
"orderId": {
$first: "$orderId"
},
"levelId": {
$first: "$levelId"
},
"screens": {
$push: "$screens"
}
}
},
{
$project: {
_id: "$_id._id",
levelId: "$levelId",
category: "category",
"orders": {
id: "$orderId",
screens: "$screens"
}
}
},
{
$group: {
_id: {
_id: "$_id",
"levelId": "$levelId",

},
"category": {
$first: "$category"
},
"levelId": {
$first: "$levelId"
},
"orders": {
$push: "$orders"
}
}
},
{
$project: {
_id: "$_id._id",
category: "category",
"levels": {
id: "$levelId",
orders: "$orders"
}
}
},
{
$group: {
_id: "$_id",
"category": {
$first: "$category"
},
"levels": {
$push: "$levels"
}
}
},

])

这是一个非常大且复杂的聚合管道,因此性能和效率不高,但您可以检查这是否适用。

说明:

  1. $match,只为聚合管道的后期阶段过滤出所需的文档集。

  2. $unroll以展开levels阵列

  3. $unroll以展开orders阵列

  4. $unroll以展开screens阵列

  5. $match以获得所需的确切screens

  6. $replaceRoot来重新构造JSON文档,这样我们就可以将未部署的数组分组

  7. $group将screens分组到屏幕阵列

  8. $项目再次重组结果文件,将原始结构放回

  9. $group将orders分组为订单阵列

  10. $项目再次重组结果文件,将原始结构放回

  11. $group将levels分组到级别数组,并返回我们的最终结果

您可以在这个Mongo Playground 上查看结果

或者,您可以运行协议管道直到第5阶段,然后将结果组合回后端代码中所需的格式。

相关内容

  • 没有找到相关文章

最新更新