可能なすべての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" } } } })