MongoDBクエリ埋め込み配列(条件を満たす配列を返すデータを限定)(1)


プロジェクトの背景
最近、プロジェクトでmongdbを使用して測定結果のモニタリングデータを保存している場合、モニタリングデータを取得する際にdoucumentに埋め込み配列が含まれており、埋め込み配列もいくつかのクラスに分かれている(識別で判断できる)ので、埋め込み配列のすべてのデータを返すのではなく、特定の配列を返す必要があります.元のデータ:
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "addTime" : ISODate("2018-03-16T03:05:04.363Z"),
    "tag" : "test",
    "userInfo" : [ 
        {
            "name" : "cj",
            "address" : "  ",
            "age" : 24.0,
            "userTag" : "stu"
        }, 
        {
            "name" : "hj",
            "address" : "  ",
            "age" : 26.0,
            "userTag" : "stu"
        }, 
        {
            "name" : "lbl",
            "address" : "  ",
            "age" : 22.0,
            "userTag" : "teach"
        }
    ]
}

クエリー条件は、tag=「test」userTag=「teach」の学生の情報です.期待される結果は次のとおりです.
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "userInfo" : [ 
        {
            "name" : "lbl",
            "address" : "  ",
            "age" : 22.0,
            "userTag" : "teach"
        }
    ]
}

多くはfindの結果はこうでした
db.test.find({"userInfo.userTag":"teach","tag":"test"})
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "addTime" : ISODate("2018-03-16T03:05:04.363Z"),
    "tag" : "test",
    "userInfo" : [ 
        {
            "name" : "cj",
            "address" : "  ",
            "age" : 24.0,
            "userTag" : "stu"
        }, 
        {
            "name" : "hj",
            "address" : "  ",
            "age" : 26.0,
            "userTag" : "stu"
        }, 
        {
            "name" : "lbl",
            "address" : "  ",
            "age" : 22.0,
            "userTag" : "teach"
        }
    ]
}

$elemMatchの説明
実は私たちは新しいことを勉強しているとき、公式のドキュメントを見に行くことをお勧めします.結局、公式のものが最も権威的です.公式住所:https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/#proj._S_elemMatch.$elemMatchはprojectionsメソッドの下にあり,projectionsは戻りフィールドを制限するメソッドを表す.変更後の方法:
db.test.find({"userInfo.userTag":"teach","tag":"test"},{"userInfo":{$elemMatch{"userTag":"teach"}}})

実行結果
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "userInfo" : [ 
        {
            "name" : "lbl",
            "address" : "  ",
            "age" : 22.0,
            "userTag" : "teach"
        }
    ]
}

やっと私の望む結果が得られたhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhそれから私はまたuserInfoを取得したいです.userTag=「stu」のデータ、簡単ですね
db.test.find({"userInfo.userTag":"teach","tag":"test"},{"userInfo":{$elemMatch:{"userTag":"stu"}}})

しかし、結果は予想外でした.
{
    "_id" : ObjectId("5aab3460353df3bd352e0e15"),
    "userInfo" : [ 
        {
            "name" : "cj",
            "address" : "  ",
            "age" : 24.0,
            "userTag" : "stu"
        }
    ]
}

2本のstuの結果なのに、なぜ1本戻るのでしょうか.実は$elemMatchの定義は公式サイトですでに話していますが、これは原話です.
The $elemMatch operator limits the contents of an  field from the query results to contain only the first element matching the $elemMatch condition.

only the first element、すなわち、最初の適切な要素のみが一致することに注意してください.では、配列に戻り要素が1つしかない場合は、$elemMatchを使用してクエリーできますが、複数の要素$elemMatchでは適応しません.
$Aggregation紹介
ドキュメントのアドレス:https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
  • $unwind: https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#pipe._S_unwind配列の各要素を各ドキュメント
  • に変換することを意味します.
  • $match: https://docs.mongodb.com/manual/reference/operator/aggregation/match/ドキュメントを簡単にフィルタし、条件クエリーを行います.
  • $project https://docs.mongodb.com/manual/reference/operator/aggregation/project/入力文書の構造を変更する
  • コマンドの実行:
    db.test.aggregate([{"$unwind":"$userInfo"},
    {"$match":{"userInfo.userTag":"stu","tag":"test"}},
    {"$project":{"userInfo":1}}])

    結果
    /* 1 */
    {
        "_id" : ObjectId("5aab3460353df3bd352e0e15"),
        "userInfo" : {
            "name" : "cj",
            "address" : "  ",
            "age" : 24.0,
            "userTag" : "stu"
        }
    }
    
    /* 2 */
    {
        "_id" : ObjectId("5aab3460353df3bd352e0e15"),
        "userInfo" : {
            "name" : "hj",
            "address" : "  ",
            "age" : 26.0,
            "userTag" : "stu"
        }
    }

    このような結果は私たちが望んでいるものです.興味のある学生はそれぞれこの3つの操作を実行することができます(3つの結果がどのように異なるかを比較してみましょう)、あなたは$unwind、$match、$projectの3つの方法の役割を理解することができます
    db.test.aggregate([{"$unwind":"$userInfo"}])
    db.test.aggregate([{"$unwind":"$userInfo"},{"$match":{"userInfo.userTag":"stu","tag":"test"}}])
    db.test.aggregate([{"$unwind":"$userInfo"},{"$match":{"userInfo.userTag":"stu","tag":"test"}},{"$project":{"userInfo":1}}])

    まとめ
  • 以前に埋め込み配列をクエリーする場合、document全体をクエリーした後、埋め込み配列をコードフィルタリングする方法が採用されています.ただ、このクエリー方式はmongodbの他の方法を使っていないと思います.やはり学習を駆動する必要があります.
  • 新しいことを学ぶには、公式ドキュメントから学ぶことをお勧めします.

  • 終了:
    次はspringでmongdbをクエリーする方法について説明します.