web-dev-qa-db-ja.com

入れ子になったオブジェクトを照会する方法

入れ子になったオブジェクトの表記法でmongoDBを照会するときに問題があります。

db.messages.find( { headers : { From: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).count()
5

自分が間違っていることがわかりません。ドット表記クエリと同じ結果が返されるように、入れ子になったオブジェクト表記を使用します。どこが悪いの?

176
Edmondo1984

db.messages.find( { headers : { From: "[email protected]" } } )

これはheaders{ From: ... }に等しい、すなわち他のフィールドを含まない文書を問い合わせます。


db.messages.find( { 'headers.From': "[email protected]" } )

これはheaders.Fromフィールドのみを調べ、headersに含まれている、またはそこから欠落している他のフィールドの影響を受けません。


ドット表記法

360
shx2

Subdocuments のセクションの docs で示唆されているように、2つの問い合わせメカニズムは異なる方法で働きます。

フィールドが埋め込みドキュメント(つまり subdocument )を保持している場合は、フィールドの値として subdocument 全体を指定できます。 サブドキュメントの個々のフィールドに値を指定するには、ドット表記を使用してサブドキュメントに「アクセスします」:

サブ文書がフィールドの順序も含めて指定されたサブ文書と完全に一致する場合、サブ文書内の等価一致は文書を選択します。


次の例では、フィールドプロデューサの値が、値'ABC123'を持つフィールドcompanyと値'123 Street'を持つフィールドaddressのみを含むサブドキュメントであるすべてのドキュメントを正確な順序で照合します。

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});
19
Edmondo1984

サブドキュメントでmongodbコレクションをクエリするについては多くの混乱があるので、上記の答えを例で説明する価値があると思いました。

最初に、コレクションに2つのオブジェクト、すなわちmessageのみを挿入しました。

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

だから、クエリの結果は何ですか:db.messages.find({headers: {From: "[email protected]"} }).count()

oneこれはheadersがオブジェクト{From: "[email protected]"}に等しい、すなわち他のフィールドのみを含まないか、またはサブドキュメント全体をフィールドの値として指定する必要があるドキュメントに対してこのクエリを実行するためです。

@ Edmondo1984からの回答によると

サブ文書が一致する場合、サブ文書内の等価一致は文書を選択しますフィールドの順序も含めて、指定されたサブ文書と正確に一致する

上記のステートメントから、以下のクエリ結果はどうなるでしょうか。

> db.messages.find({headers: {To: "[email protected]", From: "[email protected]"}  }).count()
0

FromToの順序を2番目のドキュメントのサブドキュメントと同じに変更した場合はどうなりますか。

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).count()
1

つまり、フィールドの順序も含めて、指定されたサブドキュメントと正確に一致しますに一致します。

ドット演算子を使用するために、私はそれがすべての人にとって非常に明確であると思います。以下のクエリの結果を見てみましょう。

> db.messages.find( { 'headers.From': "[email protected]" }  ).count()
2

例を使ったこの説明が誰かをより明確にすることを願っています副文書でクエリを探す

1
krishna Prasad