sql >> データベース >  >> NoSQL >> MongoDB

ExpressとMongoを使用して再帰テーブルでノードツリーを作成します

    $graphLookup を使用できます およびその他の便利な配列演算子

    • $match レコードがparent_idのみを持つフィルター nullです
    • $graphLookup 子レコードと深度番号をdepthFieldlevelで取得するには
    • $unwind childrenを分解します 配列し、空の子を削除しないようにします
    • $sort 深度レベルフィールドlevel 降順
    • $group idによる フィールドを作成してchildrenを再構築します 配列
    db.collection.aggregate([
      { $match: { parent_id: null } },
      {
        $graphLookup: {
          from: "collection",
          startWith: "$id",
          connectFromField: "id",
          connectToField: "parent_id",
          depthField: "level",
          as: "children"
        }
      },
      {
        $unwind: {
          path: "$children",
          preserveNullAndEmptyArrays: true
        }
      },
      { $sort: { "children.level": -1 } },
      {
        $group: {
          _id: "$id",
          parent_id: { $first: "$parent_id" },
          name: { $first: "$name" },
          type: { $first: "$type" },
          category: { $first: 1 },
          children: { $push: "$children" }
        }
      },
    
    • $addFields 次に、ネストされたレベルの子を見つけて、そのレベルに割り当てます。
      • $reduceを使用してchildrenのループを繰り返します 配列。
      • デフォルトフィールドのlevelを初期化します デフォルト値は-1、presentChild は[]、prevChild 条件の目的で[]です
      • $let フィールドを初期化するには:
        • prev 両方のlevelの場合、条件に従って 等しい場合はprevChildを返します それ以外の場合は、presentChildを返します
        • current 両方のlevelの場合、条件に従って 等しい場合はpresentChildを返します それ以外の場合[]
      • in levelを返す フィールドとprevChild 初期化されたフィールドからのフィールド
        • presentChild $filter children prevから 配列して戻り、現在のオブジェクトをchildrenとマージします $mergeObjectsを使用した配列 currentと連結します $concatArraysを使用したletの配列
    • $addFields presentChildのみを返す 処理された配列のみが必要だったため、配列
      {
        $addFields: {
          children: {
            $reduce: {
              input: "$children",
              initialValue: { level: -1, presentChild: [], prevChild: [] },
              in: {
                $let: {
                  vars: {
                    prev: {
                      $cond: [
                        { $eq: ["$$value.level", "$$this.level"] },
                        "$$value.prevChild",
                        "$$value.presentChild"
                      ]
                    },
                    current: {
                      $cond: [{ $eq: ["$$value.level", "$$this.level"] }, "$$value.presentChild", []]
                    }
                  },
                  in: {
                    level: "$$this.level",
                    prevChild: "$$prev",
                    presentChild: {
                      $concatArrays: [
                        "$$current",
                        [
                          {
                            $mergeObjects: [
                              "$$this",
                              {
                                children: {
                                  $filter: {
                                    input: "$$prev",
                                    as: "e",
                                    cond: { $eq: ["$$e.parent_id", "$$this.id"] }
                                  }
                                }
                              }
                            ]
                          }
                        ]
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      {
        $addFields: {
          id: "$_id",
          children: "$children.presentChild"
        }
      }
    ])
    

    遊び場




    1. Hibernateの第2レベルのキャッシュとしてRedis

    2. MongoDBでの正規表現文字列検索を高速化

    3. 長さの基準でMongoDBをクエリする

    4. MongoDBにドキュメントを挿入する5つの方法