MongoDB集約パイプラインにおけるプロジェクトの使用法


あなたがMongoDBと協力したことがある場合は、チャンスはあなたが聞いたことがあるか、さらにそれが付属の凝集パイプラインを越えて来る.MongoDBの集計パイプラインは、単純な検索操作では不可能であるあなたのデータの洞察力を得るために非常に強力な機能です.
この記事では、我々はプロジェクトの段階を取るつもりです.我々は、検索クエリのプロジェクションサポートを持っていますが、それは集約パイプラインでどのようなプロジェクト段階を達成することはできません.今日はプロジェクト段階の一般的なユースケースのいくつかを調査します.
  • すべてのフィールドを投影する
  • 配列の操作
  • プロジェクトステージの命名フィールド
  • フィルタリングフィールド
  • 文字フィールド
  • 条件的に除去するフィールド
  • データの確立


    アグリゲーションパイプラインとプロジェクトステージに飛び込む前に、データを必要とするでしょう.例を挙げているRestaurants ここでコンセプトを理解するためのコレクション.あなたが遊ぶことができて、それがどのように出力に影響するかについて見ることができるように、私は各々の質問のためにMongoDB遊び場にリンクしています.
    ここではRestaurants ランダムなデータを含む5つのドキュメントだけのコレクション:
    {
        name: 'Thai Restaurant',
        location: 'London',
        notOpenOnDays: ['Monday', 'Thursday'],
        entryFee: '$5',
        rating: '3',
    },
    {
        name: 'Indian.com',
        location: 'Broughton',
        notOpenOnDays: ['Wednesday'],
        entryFee: '$0',
        rating: '4',
    },
    {
        name: '23rd Street Pizza',
        location: 'Fallowfield',
        notOpenOnDays: ['Sunday'],
        entryFee: '$2',
        rating: '4',
    },
    {
        name: '7 STAR Pizza',
        location: 'Newcastle',
        notOpenOnDays: ['Saturday', 'Sunday'],
        entryFee: '$10',
        rating: '2',
    },
    {
        name: 'A Cake A Shake',
        location: 'London',
        notOpenOnDays: ['Monday'],
        entryFee: '$1',
        rating: '4',
    },
    

    すべてのフィールドを投影する


    MongoDB集約パイプラインでは、パイプラインステージは前の段階に含まれるそれらのフィールドだけにアクセスします.
    すべてのフィールドを含める場合は、次のいずれかに渡されるようにプロジェクトの段階ですべてを含めることができます.見逃したどんな分野でもパイプラインの次のステージにたどり着きません.
    MongoDBは私たちにどのフィールドを含めるか除外する方法を与えます.したがって、名前だけをインクルードしたい場合は、次のようになります.
    {
        $project: { name: 1 }
    }
    
    また、置くことができますtrue または1 フィールドの包含を示すために、ちょうど固執しましょう1 単純さと簡潔さのために.
    同様に、フィールドを除外する場合は、逆の操作を行います.
    {
        $project: { name: 0 }
    }
    
    そして、あなたがすべてを含むことを望むならばRestaurants コレクションは、次のようになります.
    {
        $project: {
            name: 1,
            location: 1,
            notOpenOnDays: 1,
            entryFee: 1,
            rating: 1,
        }
    }
    

    NOTE: Including a field in the project stage implicitly means excluding all the other fields and vice-versa.


    配列の操作


    配列の作成


    新しい配列フィールドを作成するのは、非配列フィールドを作成するのと同じように、[] 配列にする.
    我々はそれを行うことができますthis :
    {
        $project: {
            review: [ "$rating" ]
        }
    }
    
    現在review フィールドは評価値の配列です.

    特定のインデックスの要素を抽出する


    特定のインデックスで配列要素を取得するには、$arrayElemAt ライクshown below ,
    {
        $project: {
            fieldName: { $arrayElemAt: ["$arrayFieldName", index] }
        }
    }
    
    最新のMongoDBバージョン4.4では、配列内の最初と最後の要素を取得するために専用の演算子を持っています.演算子は$first and $last .
    To get the first element ,
    {
        $project: {
            review: [ "$rating" ]
        }
    },
    {
        $project: {
            newReview: { $first: "$review" },
            _id: 0
        }
    }
    
    レビューという名前の配列でレストラン評価を行い、次のプロジェクト段階では、ステージで作成した配列の最初の要素を抽出します.これは、
    { "newReview" : 3 }
    { "newReview" : 4 }
    { "newReview" : 4 }
    { "newReview" : 2 }
    { "newReview" : 4 }
    

    NOTE: We can chain as many project stages as we want in an aggregation pipeline.


    To get the last element ,
    {
        $project: {
            review: [ "$rating" ]
        }
    },
    {
        $project: {
            newReview: { $last: "$review" },
            _id: 0
        }
    }
    
    これは現在の配列内に1つの要素だけが存在するのと同じ出力を行います.reviews 配列.
    {
        $project: {
            review: [ 1, 2, 3, "$rating" ]
        }
    },
    {
        $project: {
            newReview: { $last: "$review" },
            _id: 0
        }
    }
    
    我々はget the ratings as the output これは最後の位置にあります.
    { "newReview" : 3 }
    { "newReview" : 4 }
    { "newReview" : 4 }
    { "newReview" : 2 }
    { "newReview" : 4 }
    

    フィルタリング値


    フィルタを使用すると、配列内のすべての要素に適用されるカスタムフィルタを作成でき、フィルターを通過する要素だけが次の段階に出力されます.
      {
        $project: {
          _id: 0,
          openOnWeekend: {
            $filter: {
              input: "$notOpenOnDays",
              as: "notOpen",
              cond: {
                $and: [
                  { $ne: ["$$notOpen", "Saturday"] },
                  { $ne: ["$$notOpen","Sunday"] },
                ]
              }
            }
          }
        }
      }
    
    Output 上記の集計クエリには、週末にオープンしているレストランだけがあります.
    [
      {
        "openOnWeekend": [ "Monday", "Thursday" ]
      },
      {
        "openOnWeekend": [ "Wednesday" ]
      },
      {
        "openOnWeekend": []
      },
      {
        "openOnWeekend": []
      },
      {
        "openOnWeekend": [ "Monday" ]
      }
    ]
    

    NOTE: We use $ for values present in our document and $$ for fields that are introduced within a pipeline stage.


    データの変換

    $map 演算子はarray.map() JavaScriptでは、入力配列を受け取り、各項目に式を適用し、変換された配列を返します.
    ここでは、適切にデータを処理するための条件を提供する必要があるフィルタと比較してデータを直接変換できます.
    変換しましょうnotOpenOnDays 曜日を短縮し、平日名を短縮します.
      {
        $project: {
          _id: 0,
          newPrice: {
            $map: {
              input: "$notOpenOnDays",
              as: "noOpenOn",
              in: {
                $substrCP: [ "$$noOpenOn", 0, 3 ]
              }
            }
          }
        }
      }
    
    部分文字列演算子をget only first 3 characters and remove the rest :
    [
      {
        "newPrice": [ "Mon", "Thu" ]
      },
      {
        "newPrice": [ "Wed" ]
      },
      {
        "newPrice": [ "Sun" ]
      },
      {
        "newPrice": [ "Sat", "Sun" ]
      },
      {
        "newPrice": [ "Mon" ]
      }
    ]
    
    他の配列式演算子の束があります.here .

    プロジェクトステージの命名フィールド


    それが命名フィールドに来るとき、集約パイプラインは大きな柔軟性を提供します.プロジェクトの段階で指定した名前は、そのフィールドからそのフィールドから“新しい”名前として機能します.
    既存のフィールドに新しい名前を付けます.
    {
        $project: {
            closedOn: "$notOpenOnDays"
        }
    }
    
    現在output が含むclosedOn フィールドnotOpenOnDays 値として配列.

    文字フィールド


    既定では、プロジェクト段階に置かれたものは、式として扱われ、値に評価されます.使えます$literal 演算子MongoDBの定数やリテラルのようなフィールドの値を扱う場合.
    入場料が「1ドル」に正確に等しいレストランを見つけたいなら、リテラル演算子を活用してこれを達成することができます.
      {
        "$project": {
          affordable: {
            $eq: [
              "$entryFee",
              {
                $literal: "$1"
              }
            ]
          }
        }
      },
      {
        "$project": {
          _id: 0,
          status: {
            "$cond": {
              "if": "$affordable",
              "then": "restaurant is affordable 🍕🍟",
              "else": "Not affordable 🙈"
            }
          }
        }
      }
    
    あなたは多くのプロジェクトの段階では、集約パイプラインで必要なチェーンすることができます.Output 上記のパイプラインの👇🏻
    [
      {
        "status": "Not affordable 🙈"
      },
      {
        "status": "Not affordable 🙈"
      },
      {
        "status": "Not affordable 🙈"
      },
      {
        "status": "Not affordable 🙈"
      },
      {
        "status": "restaurant is affordable 🍕🍟"
      }
    ]
    

    条件を除く


    上の例では、出力に冗長情報の束を見ました.我々は、それが他のものを出力しないことを意味するので、手頃な価格のレストランを知って興味があります.
    MongoDB 3.6では、条件から出力をフィールドから削除できます.上記のプロジェクト段階をoutput 手頃な価格のレストラン
      {
        "$project": {
          name: 1,
          affordable: {
            $eq: [
              "$entryFee",
              {
                $literal: "$1"
              }
            ]
          }
        }
      },
      {
        "$project": {
          _id: 0,
          status: {
            "$cond": {
              "if": "$affordable",
              "then": "$name",
              "else": "$$REMOVE"
            }
          }
        }
      }
    
  • 我々は今、それが次の段階で利用可能であることを確認する最初のプロジェクトの段階で名前を含んでいる.
  • $cond 演算子は、手頃な価格のレストランの名前を表示するように更新されます.
  • 出力:
    [
      {},
      {},
      {},
      {},
      {
        "status": "A Cake A Shake"
      }
    ]
    

    結論


    ですから、MongoDB集約パイプラインのプロジェクト段階は、単にフィールドを含めたり除外したりするよりもずっと多くのことをすることができます.配列を作成したり、その要素を変更したり、フィルタを実行したり、スライス文字列を実行したり、条件を削除したり、必要に応じてデータを取得したりできます.
    何かが不足しているか、または任意の質問があると思う場合は、コメントを投稿してください.私は、接続して満足です!