mongodb聚合以扁平化递归子文档

vwkv1x7d  于 2023-10-16  发布在  Go
关注(0)|答案(1)|浏览(126)

使用MongoDB和下面的文档。

  1. {
  2. "_id": "7741cca6-31d4-4652-aa00-a7d547a16a2e",
  3. "kids": [
  4. {
  5. "_id": "e6c2f07e-899f-40b5-8ac2-9a587f26d67e",
  6. "kids": [
  7. {
  8. "_id": "e9b35574-add7-490e-ab9d-9b2d425bebf6",
  9. "kids": [
  10. {
  11. "_id": "25f6e89d-6f77-4a7f-948b-77488578710f"
  12. }
  13. ]
  14. }
  15. ]
  16. }
  17. ]
  18. }

我想创建一个聚合,将展开“孩子”到一个文档,只有一个层次深,如下图所示:

  1. {
  2. "_id": "7741cca6-31d4-4652-aa00-a7d547a16a2e",
  3. "kids": [
  4. {
  5. "_id": "e6c2f07e-899f-40b5-8ac2-9a587f26d67e"
  6. },
  7. {
  8. "_id": "e9b35574-add7-490e-ab9d-9b2d425bebf6"
  9. },
  10. {
  11. "_id": "25f6e89d-6f77-4a7f-948b-77488578710f"
  12. }
  13. ]
  14. }

我该怎么做?
我试过使用$project,$lookup,$unwind,$reduce,但似乎不能让它工作。我可以用JavaScript查询和递归函数来实现,但我希望这最终是一个视图。
这是我所做的最接近的事情,但是最后添加的文档是数组中的数组,而不是数组中的文档。

  1. [
  2. {
  3. $addFields:
  4. /**
  5. * newField: The new field name.
  6. * expression: The new field expression.
  7. */
  8. {
  9. newKids: {
  10. $reduce: {
  11. input: "$kids.kids.kids",
  12. initialValue: [],
  13. in: {
  14. $concatArrays: [
  15. "$$value",
  16. "$$this",
  17. ],
  18. },
  19. },
  20. },
  21. },
  22. },
  23. {
  24. $addFields:
  25. /**
  26. * newField: The new field name.
  27. * expression: The new field expression.
  28. */
  29. {
  30. newKids: {
  31. $reduce: {
  32. input: "$kids.kids",
  33. initialValue: "$newKids",
  34. in: {
  35. $concatArrays: [
  36. "$$value",
  37. "$$this",
  38. ],
  39. },
  40. },
  41. },
  42. },
  43. },
  44. {
  45. $addFields:
  46. /**
  47. * newField: The new field name.
  48. * expression: The new field expression.
  49. */
  50. {
  51. newKids: {
  52. $reduce: {
  53. input: ["$kids"],
  54. initialValue: "$newKids",
  55. in: {
  56. $concatArrays: [
  57. "$$value",
  58. "$$this",
  59. ],
  60. },
  61. },
  62. },
  63. },
  64. },
  65. ]
mctunoxg

mctunoxg1#

我不是JavaScript向导,但如果MongoDB服务器上启用了JavaScript,您可以使用"$function"实现递归下降。
N.B.:可能有更好的方法来实现这一点。

  1. db.collection.aggregate([
  2. {
  3. "$set": {
  4. "kids": {
  5. "$function": {
  6. "body": "function drill(kids, out) {if (kids.length > 0) {for (let elem of kids) {out.push({_id: elem._id}); drill(elem.kids??[], out)}}; return out};",
  7. "args": [ "$kids", [] ],
  8. "lang": "js"
  9. }
  10. }
  11. }
  12. }
  13. ])

使用示例文档输出:

  1. [
  2. {
  3. "_id": "7741cca6-31d4-4652-aa00-a7d547a16a2e",
  4. "kids": [
  5. {
  6. "_id": "e6c2f07e-899f-40b5-8ac2-9a587f26d67e"
  7. },
  8. {
  9. "_id": "e9b35574-add7-490e-ab9d-9b2d425bebf6"
  10. },
  11. {
  12. "_id": "25f6e89d-6f77-4a7f-948b-77488578710f"
  13. }
  14. ]
  15. }
  16. ]

mongoplayground.net上试试。

展开查看全部

相关问题