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

$graphLookupでMongodb再帰クエリが期待どおりに機能しない

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

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

    遊び場




    1. グラフDBとドキュメントDBとトリプルストア

    2. Redis:通常のセットをソートされたセットと交差させる方法は?

    3. Railsキャッシングを使用する場合のRailsでのredismaxmemoryシチュエーションの処理

    4. シャードキーなしのすべてのシャードコレクションに対するMongoDBクエリ