ネストされたオブジェクトをクエリする方法は?


204

ネストされたオブジェクト表記でmongoDBをクエリするときに問題があります。

db.messages.find( { headers : { From: "reservations@marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
5

何が悪いのか分かりません。ネストされたオブジェクト表記がドット表記クエリと同じ結果を返すことを期待しています。どこが間違っているのですか?

回答:


419

db.messages.find( { headers : { From: "reservations@marriott.com" } } )

これheaders { From: ... }等しい、つまり他のフィールドを含まないドキュメントを照会します。


db.messages.find( { 'headers.From': "reservations@marriott.com" } )

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


ドット表記ドキュメント


「headers.From」の周りの引用符なしでこれを行う方法はありますか?
トリシス14年

わからない、ただ疑問に思っている、そしてそれが時々役立つかもしれないと思った。
トリシス2014年

3
@trysis-実際には、インラインオブジェクト(mongo [ose]ドキュメントの例や、ほとんどの例のような)を宣言するだけでは、現実の世界では不十分であることがわかりました。私はのようなものを行うことができた上で「条件」と「フィールド」オブジェクト作成の習慣を開発しているconditions['some.path'] = 'value':私のビジネスロジックでは、その後、最後に単一のクエリを実行find(conditions, fields, callback);
ライアンWheale

「domain.com」を含むキーがあるとしましょうdomains.domain.com。これは機能しません。このシナリオの回避策はありますか(domain.comを他のもの(domain_comなど)に変更せずに)?
Rens Tillmann

1
私自身のコメントに答えて、キーでドットを完全に使用しないことをお勧めします。私のソリューションでは、ドメインをキーとして完全に破棄し、代わりにスライス/アレイを作成しました。
Rens Tillmann

20

2つのクエリメカニズムは、サブドキュメントセクションのドキュメントで提案されいるようにさまざまな方法で機能します。

フィールドが埋め込まれた文書(すなわち、保持しているときにサブドキュメントを)、あなたはどちらか全体を指定することができますサブドキュメントを「に到達する」フィールドの値として、またはサブドキュメント内の個々のフィールドの値を指定するために、ドット表記を使用したサブ文書を

サブドキュメントがフィールド順序を含め、指定されたサブドキュメントと完全に一致する場合、サブドキュメント内の同等一致はドキュメントを選択します。


次の例では、クエリは、フィールドプロデューサーの値がフィールドのみが含まれているサブ文書のすべての文書と一致するcompany値と'ABC123'し、フィールドaddress値を持つ'123 Street':正確な順序では、

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

8
私は夢中になりました。オブジェクトをクエリするとき、その直接プロパティは任意の順序で照合できるため、これは私にはかなり一貫性がないようです。
Capaj 2015年

7

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

まず、コレクションにオブジェクトを2つだけ挿入しmessageました。

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "reservations@marriott.com"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "reservations@marriott.com",
        "To" : "kprasad.iitd@gmail.com"
    }
}
>

だからクエリの結果は何ですか: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

オブジェクトと等しいドキュメントに対するこれらのクエリ、つまり他のフィールドが含まれていないか、サブドキュメント全体をフィールドの値として指定する必要があるため、これらのクエリは1である必要があります。headers{From: "reservations@marriott.com"}

@ Edmondo1984からの回答に従って

サブドキュメント内の等価一致では、サブドキュメントがフィールドの順序を含め、指定されたサブドキュメントと完全に一致する場合、ドキュメントが選択されます

上記のステートメントから、以下のクエリ結果はどうあるべきですか?

> db.messages.find({headers: {To: "kprasad.iitd@gmail.com", From: "reservations@marriott.com"}  }).count()
0

そして、もし私たちが2番目のドキュメントのサブドキュメントの順序を変更するFromToつまり同じ場合はどうでしょうか?

> db.messages.find({headers: {From: "reservations@marriott.com", To: "kprasad.iitd@gmail.com"}  }).count()
1

そのため、フィールドの順序を含め、指定されたサブドキュメントと完全に一致します

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

> db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
2

上記の例に関するこれらの説明が、サブドキュメントを使用し検索クエリをより明確にすることを願っています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.