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

ネストされた配列のMongoDBプロジェクション

    2017アップデート

    そのようなよくできた質問は、現代の回答に値します。要求された種類の配列フィルタリングは、実際には、$matchを介して3.2以降の最新のMongoDBリリースで実行できます。 および$project パイプラインステージは、元のプレーンクエリ操作が意図するものとよく似ています。

    db.accounts.aggregate([
      { "$match": {
        "email" : "[email protected]",
        "groups": {
          "$elemMatch": { 
            "name": "group1",
            "contacts.localId": { "$in": [ "c1","c3", null ] }
          }
        }
      }},
      { "$addFields": {
        "groups": {
          "$filter": {
            "input": {
              "$map": {
                "input": "$groups",
                "as": "g",
                "in": {
                  "name": "$$g.name",
                  "contacts": {
                    "$filter": {
                      "input": "$$g.contacts",
                      "as": "c",
                      "cond": {
                        "$or": [
                          { "$eq": [ "$$c.localId", "c1" ] },
                          { "$eq": [ "$$c.localId", "c3" ] }
                        ]
                      } 
                    }
                  }
                }
              }
            },
            "as": "g",
            "cond": {
              "$and": [
                { "$eq": [ "$$g.name", "group1" ] },
                { "$gt": [ { "$size": "$$g.contacts" }, 0 ] }
              ]
            }
          }
        }
      }}
    ])
    

    これは$filterを利用します および$map 演算子は、条件を満たす場合にのみ配列から要素を返すため、$unwindを使用するよりもパフォーマンスがはるかに優れています。 。パイプラインステージは、.find()からの「query」と「project」の構造を効果的に反映しているため 操作、ここでのパフォーマンスは基本的にそのような操作と同等です。

    「ドキュメント間」で実際に作業することを意図している場合は注意してください 「1つ」ではなく「複数の」ドキュメントから詳細をまとめるには、通常、何らかのタイプの$unwindが必要になります。 これを行うための操作。これにより、「グループ化」のために配列アイテムにアクセスできるようになります。

    これが基本的なアプローチです:

    db.accounts.aggregate([
        // Match the documents by query
        { "$match": {
            "email" : "[email protected]",
            "groups.name": "group1",
            "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
        }},
    
        // De-normalize nested array
        { "$unwind": "$groups" },
        { "$unwind": "$groups.contacts" },
    
        // Filter the actual array elements as desired
        { "$match": {
            "groups.name": "group1",
            "groups.contacts.localId": { "$in": [ "c1","c3", null ] },
        }},
    
        // Group the intermediate result.
        { "$group": {
            "_id": { "email": "$email", "name": "$groups.name" },
            "contacts": { "$push": "$groups.contacts" }
        }},
    
        // Group the final result
        { "$group": {
            "_id": "$_id.email",
            "groups": { "$push": {
                "name": "$_id.name",
                "contacts": "$contacts" 
            }}
        }}
    ])
    

    これは、.find()の基本的な投影機能である複数の一致に対する「配列フィルタリング」です。 できません。

    「ネストされた」配列があるため、 $unwindを処理する必要があります 2回。他の操作と一緒に。



    1. Redis-cli --csvオプション(csvへのエクスポート)

    2. MongoDBドキュメントフィールドが存在しない場合にのみ更新するにはどうすればよいですか?

    3. phpredisMACOSXをインストールします

    4. 合計16MBの制限を回避する