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

配列のサブドキュメントにフィールドが存在するかどうかを確認します

    基本的には、 $elemMatchが必要です。 および $exists 演算子。これにより、各要素が検査され、「フィールドが存在しない」という条件がどの要素にも当てはまるかどうかが確認されます。

    Model.find({
      "line_items": {
          "$elemMatch": { "review_request_sent": { "$exists": false } }
      }
    },function(err,docs) {
    
    });
    

    フィールドが配列サブドキュメントの1つに存在しないため、2番目のドキュメントのみが返されます。

    {
            "id" : 2,
            "line_items" : [
                    {
                            "id" : 1,
                            "review_request_sent" : false
                    },
                    {
                            "id" : 39
                    }
            ]
    }
    

    これはこのフォームとは「異なる」ことに注意してください:

    Model.find({
      "line_items.review_request_sent": { "$exists": false } 
    },function(err,docs) {
    
    })
    

    それが求めているのは、配列要素の「すべて」にこのフィールドが含まれていないことです。これは、フィールドが存在する要素がドキュメントに少なくとも1つある場合には当てはまりません。したがって、$eleMatch 条件を「各」配列要素に対してテストするため、正しい応答が得られます。

    このデータを更新して、このフィールドを含まない配列要素が見つかった場合は、falseの値でそのフィールドを受け取ることになります。 (おそらく)、次のようなステートメントを書くこともできます:

        Model.aggregate(
          [
            { "$match": { 
              "line_items": {
                "$elemMatch": { "review_request_sent": { "$exists": false } }
              } 
            }},
            { "$project": {
              "line_items": {
                "$setDifference": [
                  {"$map": {
                    "input": "$line_items",
                    "as": "item",
                    "in": {
                      "$cond": [
                        { "$eq": [ 
                          { "$ifNull": [ "$$item.review_request_sent", null ] },
                          null
                        ]},
                        "$$item.id",
                        false
                      ]
                    }
                  }},
                  [false]
                ]
              }
            }}
        ],
        function(err,docs) {
          if (err) throw err;
          async.each(
            docs,
            function(doc,callback) {
              async.each(
                doc.line_items,
                function(item,callback) {
                  Model.update(
                    { "_id": doc._id, "line_items.id": item },
                    { "$set": { "line_items.$.review_request_sent": false } },
                    callback
                  );
                },
                callback
              );
            },
            function(err) {
              if (err) throw err;
              // done
            }
          );
        }
      );
    

    .aggregate()の場所 結果はドキュメントと一致するだけでなく、フィールドが存在しなかった配列からコンテンツを除外して、その特定のサブドキュメントの「id」を返すだけです。

    次に、ループした.update() ステートメントは、各ドキュメントで見つかった各配列要素と一致し、欠落しているフィールドに一致した位置の値を追加します。

    このようにして、以前は欠落していたすべてのドキュメントのすべてのサブドキュメントにフィールドが存在するようになります。

    そのようなことをしたい場合は、スキーマを変更して、フィールドも常にそこにあることを確認することも賢明です:

    {id: Number,
      line_items: [{ 
        id: String,
        quantity: Number,
        review_request_sent: { type: Boolean, default: false }
      }],
      total_price: String,
      name: String,
      order_number: Number
    }
    

    したがって、次にコードの配列に新しい項目を追加するとき、明示的に設定されていない限り、要素は常にデフォルト値で存在します。そして、requiredを設定するだけでなく、そうすることはおそらく良い考えです。 「id」など、常に必要な他のフィールド。



    1. node.jsのmongodb4.0トランザクションのサポート

    2. マングースでコレクション名とモデル名を宣言する方法

    3. 異なる言語(英語以外)のデータをMongoDBフィールドに保存し、同じデータを取得するにはどうすればよいですか?

    4. フィールドの大きな組み合わせが存在する場合にMongoDBでインデックスを作成する正しい方法は何ですか