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

ネストされたドキュメントによるmongodb集約フレームワークの一致

    可能なすべてのformsを知らなければ、この構造をクエリして必要な結果を得ることができません。 事前に名前を付け、クエリで使用します。とにかくそれは非常に厄介でしょう。そうは言っても、それがどのように行われるかを説明しながら読んでください。

    これらのドキュメントの構造に問題があり、適切なクエリ分析を行うことができません。現状では、何かを除外するには、可能なすべてのフォーム名フィールドを知っている必要があります。

    現在の構造にはサブドキュメントを含むフォームがあり、その各キーには、statusという単一のプロパティを持つ別のサブドキュメントが含まれています。 。 formsとして、これをトラバースするのは困難です 要素には、作成するドキュメントごとに任意の構造があります。つまり、下降するパターンを意味します statusに コレクション内のすべてのドキュメントの変更を比較する情報。

    これが私がパスによって意味するものです。任意の要素のステータスを取得するには、次のことを行う必要があります

    2番目の要素は常に変化しています。 方法はありません ワイルドカード 命名は明示的であると見なされるため、このようなものです。

    これは、フォームからのデータのシリアル化を実装する簡単な方法と見なされている可能性があります。 しかし、より柔軟だと思います 別。必要なのは、標準パターンでトラバースできるドキュメント構造です。これは、設計において常に考慮する価値のあるものです。次のことを行ってください:

    {
        "_id" : "Tvq444454j",
        "name": "Jim",
        "forms": [
            {
                 "name": "Jorney",
                 "status":"closed"          
            },
            {
                "name": "Women",
                "status":"void"            
            },
            {
                "name": "Child",
                "status":"closed"           
            },
            {
                "name": "Farm",
                "status":"closed"            
            }  
        ]
    }
    

    そのため、ドキュメントの構造が変更され、formsが作成されます。 配列を要素化し、ステータスフィールドを「フォームフィールド」という名前のキーの下に配置するのではなく、配列の各メンバーを「フォームフィールド」nameを含むサブドキュメントとして使用します。 およびstatus 。したがって、識別子とステータスの両方はまだペアになっていますが、現在はサブドキュメントとして表されています。これは最も重要なことですが、両方の場合と同様に、これらのキーへのアクセスパスを変更します。 フィールド名とそのステータス

    これ つまり、formのすべてのフィールドの名前を検索するためにクエリを実行できます またはすべてのstatus formのフィールド 、または特定のnameを持つすべてのドキュメント フィールドと特定のstatus 。それは大いに 元の構造でできることよりも優れています。

    今、あなたの特定のケースでは、のみを取得したいです すべてのドキュメント フィールドはvoidではありません 。この方法で配列内のすべての要素を比較し、それらが同じであるかどうかを確認する演算子がないため、単一のクエリでこれを行う方法はありません。ただし、実行できるアプローチは2つあります。

    最初の、おそらくそれほど効率的ではないのは、すべてをクエリすることです。 formsの要素を含むドキュメント statusがあります 「ボイド」の。結果のドキュメントIDを使用して、しないドキュメントを返す別のクエリを発行できます。 指定されたIDを持っています。

    db.forms.find({ "forms.status": "void" },{ _id: 1})
    
    db.forms.find({ _id: $not: { $in: [<Object1>,<Object2>,<Object3>,... ] } })
    

    結果のサイズを考えると、これは不可能な場合があり、除外演算子$notとして、一般的にはお勧めできません。 基本的にフルスキャンを強制します コレクションの一部であるため、インデックスを使用できませんでした。

    もう1つのアプローチは、次のように集約パイプラインを使用することです。

    db.forms.aggregate([
        { "$unwind": "$forms" },
        { "$group": { "_id": "$_id", "status": { "$addToSet": "$forms.status" }}},
        { "$unwind": "$status" },
        { "$sort": { "_id": 1, "status": -1 }},
        { "$group": { "_id": "$_id", "status": { "$first": "$status"}}},
        { "$match":{ "status": "closed" }}
    ])
    

    もちろん、これは一致するドキュメントの_idのみを返しますが、$ inを使用してクエリを発行し、一致するドキュメント全体を返すことができます。これは、以前に使用されていた除外演算子よりも優れており、インデックスを使用して完全なコレクションスキャンを回避できるようになりました。

    ファイナルアプローチとして、そしてベスト パフォーマンスを考慮して、ドキュメントを再度変更して、フォームのフィールドが「void」または「closed」であるかどうかの「ステータス」をトップレベルで保持できるようにすることができます。したがって、最上位レベルでは、すべてのアイテムが「閉じられた」場合にのみ値が閉じられ、何かが無効な場合は「無効」になります。

    その最後のものは、さらなるプログラムの変更、およびformsへのすべての変更を意味します アイテムは、「ステータス」を維持するためにこのフィールドも更新する必要があります。ただし、これは必要なドキュメントを見つけるための最も効率的な方法であり、検討する価値があるかもしれません。

    編集

    ドキュメントをマスターステータスに変更する以外に、改訂された構造での最速のクエリフォームは実際には次のとおりです。

    db.forms.find({ "forms": { "$not": { "$elemMatch": { "status": "void" } } } })
    



    1. ClusterControl 1.7.1の発表:PostgreSQL11とMongoDB4.0のサポート、拡張モニタリング

    2. MongoDB:ネストされた配列を1つのドキュメントにグループ化する方法は?

    3. ApacheDrill-最初の開始時間が長い

    4. マングースの接続を手動で閉じる必要がありますか?