如何访问mongodb中多嵌套文档中的数据?

时间:2021-07-09 04:39:49

标签: node.js mongodb mongodb-query aggregation-framework nosql-aggregation

我需要通过省略嵌套文档的某些字段来访问多嵌套子文档中的数据。架构如下所示,预期的输出也如下所示。由于无法在嵌套级别使用投影,所以我该怎么做?

下面给出的是具有嵌套条目的数据库架构,如图所示。

[
  {
    "_id": {
      "$oid": "60e519db4e0f140328adc7c7"
    },
    "trans": {
      "en": {
        "name": "Graphics And Design",
        "description": "Graphics And Design"
      },
      
    },
    "counts": {
      "$numberInt": "0"
    },
    "is_visible": true,
    "slug": "graphics-and-design",
    "image": "",
    "created_at": {
      "$numberDouble": "1625627099104.0"
    },
    "subcategories": [
      {
        "trans": {
          "en": {
            "name": "LOGO DESIGN",
            "description": "LOGO DESIGN"
          },
          "fr": {
            "name": "LOGO DESIGN",
            "description": "LOGO DESIGN"
          }
        },
        "counts": {
          "$numberInt": "0"
        },
        "slug": "logo-design",
        "is_visible": true,
        "image": "",
        "_id": {
          "$oid": "60e51a116678530e84ee2e61"
        },
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "service_type": [
          {
            "trans": {
              "en": {
                "name": "3D logo",
                "description": "3D logo design"
              },
              "fr": {
                "name": "3D logo",
                "description": "3D logo design"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e60"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          }
        ]
      },
      {
        "trans": {
          "en": {
            "name": "BRAND STYLE GUIDES",
            "description": "BRAND STYLE GUIDES"
          },
          "fr": {
            "name": "BRAND STYLE GUIDES",
            "description": "BRAND STYLE GUIDES"
          }
        },
        "counts": {
          "$numberInt": "0"
        },
        "slug": "brand-style-guides",
        "is_visible": true,
        "image": "",
        "_id": {
          "$oid": "60e51a116678530e84ee2e63"
        },
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "service_type": [
          {
            "trans": {
              "en": {
                "name": "Brand style 1",
                "description": "Brand style 1"
              },
              "fr": {
                "name": "Brand style 1",
                "description": "Brand style 1"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e62"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          },
          {
            "trans": {
              "en": {
                "name": "Brand style 2",
                "description": "Brand style 2"
              },
              "fr": {
                "name": "Brand style 2",
                "description": "Brand style 2"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e62"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          }
        ]
      }
    ],
    "updated_at": {
      "$date": {
        "$numberLong": "1625627153547"
      }
    }
  },
//this is the another category
  {
    "_id": {
      "$oid": "60e519db4e0f140328adc7c8"
    },
    "trans": {
      "en": {
        "name": "Graphics And Design2",
        "description": "Graphics And Design2"
      },
      "fr": {
        "name": "Graphics And Design2",
        "description": "Graphics And Design2"
      }
    },
    "counts": {
      "$numberInt": "0"
    },
    "is_visible": true,
    "slug": "graphics-and-design2",
    "image": "",
    "created_at": {
      "$numberDouble": "1625627099104.0"
    },
    "subcategories": [
      {
        "trans": {
          "en": {
            "name": "LOGO DESIGN2",
            "description": "LOGO DESIGN2"
          },
          "fr": {
            "name": "LOGO DESIGN2",
            "description": "LOGO DESIGN2"
          }
        },
        "counts": {
          "$numberInt": "0"
        },
        "slug": "logo-design2",
        "is_visible": true,
        "image": "",
        "_id": {
          "$oid": "60e51a116678530e84ee2e61"
        },
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "service_type": [
          {
            "trans": {
              "en": {
                "name": "3D logo2",
                "description": "3D logo design2"
              },
              "fr": {
                "name": "3D logo2",
                "description": "3D logo design2"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e60"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          }
        ]
      },
      {
        "trans": {
          "en": {
            "name": "BRAND STYLE GUIDES2",
            "description": "BRAND STYLE GUIDES2"
          },
          "fr": {
            "name": "BRAND STYLE GUIDES2",
            "description": "BRAND STYLE GUIDES2"
          }
        },
        "counts": {
          "$numberInt": "0"
        },
        "slug": "brand-style-guides2",
        "is_visible": true,
        "image": "",
        "_id": {
          "$oid": "60e51a116678530e84ee2e63"
        },
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "service_type": [
          {
            "trans": {
              "en": {
                "name": "Brand style 12",
                "description": "Brand style 12"
              },
              "fr": {
                "name": "Brand style 12",
                "description": "Brand style 12"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e62"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          },
          {
            "trans": {
              "en": {
                "name": "Brand style 22",
                "description": "Brand style 22"
              },
              "fr": {
                "name": "Brand style 22",
                "description": "Brand style 22"
              }
            },
            "counts": {
              "$numberInt": "0"
            },
            "is_visible": true,
            "_id": {
              "$oid": "60e51a116678530e84ee2e62"
            },
            "image": "",
            "slug": "null",
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": []
          }
        ]
      }
    ],
    "updated_at": {
      "$date": {
        "$numberLong": "1625627153547"
      }
    }
  }
]

到目前为止我尝试过的代码:

 const client = await Database.connect();
        const lang = "en";
        const r = await client
          .collection("categories")
          .aggregate([
            {
              $addFields: {
                categories: {
                  $map: {
                    input: "$categories",
                    as: "c",
                    in: {
                      $mergeObjects: [
                        "$$this",
                        {
                          trans: `$$c.trans.${lang}`,

                          subcategories: {
                            $map: {
                              input: "$subcategories",
                              as: "s",
                              in: {
                                $mergeObjects: [
                                  "$$this",
                                  {
                                    trans: `$$s.trans.${lang}`,
                                    service_type: {
                                      $map: {
                                        input: "$$s.service_type",
                                        as: "d",
                                        in: {
                                          $mergeObjects: [
                                            "$$this",
                                            { trans: `$$d.trans.${lang}` },
                                          ],
                                        },
                                      },
                                    },
                                  },
                                ],
                              },
                            },
                          },
                        },
                      ],
                    },
                  },
                },
              },
            },
          ])
          .toArray();
        console.log(r);

console.log(r) 的响应:

:: FieldPath field names may not start with '$'

预期输出:

[
  {
    "_id": ObjectId("60e519db4e0f140328adc7c7"),
    "counts": 0,
    "created_at": {
      "$numberDouble": "1625627099104.0"
    },
    "image": "",
    "is_visible": true,
    "slug": "graphics-and-design",
    "subcategories": [
      {
        "_id": ObjectId("60e51a116678530e84ee2e61"),
        "counts": 0,
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "image": "",
        "is_visible": true,
        "service_type": [
          {
            "_id": ObjectId("60e51a116678530e84ee2e60"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "service_type1",
            "trans": {
              "description": "service_type1",
              "name": "service_type1"
            }
          }
        ],
        "slug": "logo-design",
        "trans": {
          "description": "LOGO DESIGN",
          "name": "LOGO DESIGN"
        }
      },
      {
        "_id": ObjectId("60e51a116678530e84ee2e63"),
        "counts": 0,
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "image": "",
        "is_visible": true,
        "service_type": [
          {
            "_id": ObjectId("60e51a116678530e84ee2e62"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "null",
            "trans": {
              "description": "ServiceType1_BRAND STYLE GUIDES",
              "name": "ServiceType1_BRAND STYLE GUIDES"
            }
          },
          {
            "_id": ObjectId("60e51a116678530e84ee2e62"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "null",
            "trans": {
              "description": "ServiceType2_BRAND STYLE GUIDES",
              "name": "ServiceType2_BRAND STYLE GUIDES"
            }
          }
        ],
        "slug": "brand-style-guides",
        "trans": {
          "description": "BRAND STYLE GUIDES",
          "name": "BRAND STYLE GUIDES"
        }
      }
    ],
    "trans": {
      
        "description": "Graphics And Design",
        "name": "Graphics And Design"
     
    },
    "updated_at": ISODate("2021-07-07T03:05:53.547Z")
  },
  {
    "_id": ObjectId("60e519db4e0f140328adc7c8"),
    "counts": 0,
    "created_at": {
      "$numberDouble": "1625627099104.0"
    },
    "image": "",
    "is_visible": true,
    "slug": "graphics-and-design2",
    "subcategories": [
      {
        "_id": ObjectId("60e51a116678530e84ee2e61"),
        "counts": 0,
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "image": "",
        "is_visible": true,
        "service_type": [
          {
            "_id": ObjectId("60e51a116678530e84ee2e60"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "null",
            "trans": {
              "description": "ServiceType1_LOGO DESIGN2",
              "name": "ServiceType1_LOGO DESIGN2"
            }
          }
        ],
        "slug": "logo-design2",
        "trans": {
          "description": "LOGO DESIGN2",
          "name": "LOGO DESIGN2"
        }
      },
      {
        "_id": ObjectId("60e51a116678530e84ee2e63"),
        "counts": 0,
        "created_at": {
          "$numberDouble": "1625627153535.0"
        },
        "image": "",
        "is_visible": true,
        "service_type": [
          {
            "_id": ObjectId("60e51a116678530e84ee2e62"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "null",
            "trans": {
              "description": "ServiceType1_BRAND STYLE GUIDES2",
              "name": "ServiceType1_BRAND STYLE GUIDES2"
            }
          },
          {
            "_id": ObjectId("60e51a116678530e84ee2e62"),
            "counts": 0,
            "created_at": {
              "$numberDouble": "1625627153535.0"
            },
            "gig_meta_data": [],
            "image": "",
            "is_visible": true,
            "slug": "null",
            "trans": {
              "description": "ServiceType2_BRAND STYLE GUIDES2",
              "name": "ServiceType2_BRAND STYLE GUIDES2"
            }
          }
        ],
        "slug": "brand-style-guides2",
        "trans": {
          "description": "BRAND STYLE GUIDES2",
          "name": "BRAND STYLE GUIDES2"
        }
      }
    ],
    "trans": {
        "description": "Graphics And Design2",
        "name": "Graphics And Design2"
    },
    "updated_at": ISODate("2021-07-07T03:05:53.547Z")
  }
]

请以任何好的和有效的方法帮助解决这个问题。

1 个答案:

答案 0 :(得分:1)

我没有得到你的尝试,你可以试试下面的方法,

  • $map 迭代 subcategories 数组的循环
  • $map 迭代 service_type 数组的循环
  • 按输入语言选择 trans 对象
  • $mergeObjects 合并更新的 trans 字段和 service_type 数组的当前对象
  • $mergeObjects 将更新后的 transservice_type 数组与 subcategories 数组的当前对象合并
var lang = "en";
const r = await client.collection("categories").aggregate([
  {
    $addFields: {
      trans: "$trans.en",
      subcategories: {
        $map: {
          input: "$subcategories",
          as: "s",
          in: {
            $mergeObjects: [
              "$$s",
              {
                trans: `$$s.trans.${lang}`,
                service_type: {
                  $map: {
                    input: "$$s.service_type",
                    in: {
                      $mergeObjects: ["$$this", { trans: `$$this.trans.${lang}` }]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
]).toArray();
console.log(r);

Playground