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

MongoDBコレクションで特定の基準に一致するドキュメントと単一のサブドキュメントを見つける方法

    探しているのは、位置の$です。 演算子と「投影」。単一のフィールドの場合は「ドット表記」を使用して必要な配列要素を一致させる必要があり、複数のフィールドの場合は $elemMatch

    db.products.find(
        { "items.date": "31.08.2014" },
        { "shop": 1, "name":1, "items.$": 1 }
    )
    

    または$elemMatch 複数の一致するフィールドの場合:

    db.products.find(
        { "items":  { 
            "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
        }},
        { "shop": 1, "name":1, "items.$": 1 }
    )
    

    ただし、これらは単一の配列要素に対してのみ機能し、1つだけが返されます。条件から複数の配列要素を返す場合は、集計フレームワークを使用したより高度な処理が必要です。

    db.products.aggregate([
        { "$match": { "items.date": "31.08.2014" } },
        { "$unwind": "$items" },
        { "$match": { "items.date": "31.08.2014" } },
        { "$group": {
            "_id": "$_id",
            "shop": { "$first": "$shop" },
            "name": { "$first": "$name" },
            "items": { "$push": "$items" }
        }}
    ])
    

    または、アイテムの配列に一意のエントリが含まれているMongoDB 2.6以降、より短い/より高速な形式である可能性があります:

    db.products.aggregate([
        { "$match": { "items.date": "31.08.2014" } },
        { "$project": {
            "shop": 1,
            "name": 1,
            "items": {
                "$setDifference": [
                    { "$map": {
                        "input": "$items",
                        "as": "el",
                        "in": {
                            "$cond": [
                                { "$eq": [ "$$el.date", "31.08.2014" ] },
                                "$$el",
                                false 
                            ]
                        }
                    }},
                    [false]
                ]
            }
        }}
    ])
    

    または、 $redact 、しかし少し不自然です:

    db.products.aggregate([
        { "$match": { "items.date": "31.08.2014" } },
        { "$redact": {
            "$cond": [
                 { "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
                 "$$DESCEND",
                 "$$PRUNE"
             ]
        }}
    ])
    

    より現代的には、$filterを使用します :

    db.products.aggregate([
      { "$match": { "items.date": "31.08.2014" } },
      { "$addFields": {
        "items": {
          "input": "$items",
          "cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
        }
      }}
    ])
    

    また、複数の条件がある場合、$elemMatch および$and $filter内 :

    db.products.aggregate([
      { "$match": { 
        "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
      }},
      { "$addFields": {
        "items": {
          "input": "$items",
          "cond": { 
            "$and": [
              { "$eq": [ "$$this.date", "31.08.2014" ] },
              { "$eq": [ "$$this.purchasePrice", 1 ] }
            ]
          }
        }
      }}
    ])
    

    したがって、単一の要素が一致することを常に期待するか、複数の要素が一致することを常に期待するか、そしてどちらのアプローチが優れているかによって異なります。ただし、可能な場合は.find() メソッドは、他の操作のオーバーヘッドがないため、一般的に高速になります。これは、最後のフォームでは、それほど遅れることはありません。

    ちなみに、あなたの「日付」は文字列として表されますが、これは今後あまり良い考えではありません。これらを適切な日付に変更することを検討してください。 オブジェクトタイプ。将来的に非常に役立ちます。



    1. mongodbで集計中にフィールドを条件付きで投影する方法

    2. マングースの個別の関数は、クエリで正規表現をサポートしていますか?

    3. Robomongo:$groupのメモリ制限を超えました

    4. C#ドライバーを使用してMongoDBにコレクションが存在するかどうかを確認するにはどうすればよいですか?