Làm thế nào để truy vấn các đối tượng lồng nhau?


204

Tôi gặp vấn đề khi truy vấn mongoDB với ký hiệu đối tượng lồng nhau:

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

Tôi không thể thấy những gì tôi đang làm sai. Tôi hy vọng ký hiệu đối tượng lồng nhau sẽ trả về kết quả giống như truy vấn ký hiệu dấu chấm. Tôi sai ở đâu

Câu trả lời:


419

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

Truy vấn này cho các tài liệu headers bằng { From: ... } , tức là không chứa các trường khác.


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

Điều này chỉ nhìn vào headers.Fromtrường, không bị ảnh hưởng bởi các trường khác có trong hoặc thiếu từ , headers.


Tài liệu ký hiệu chấm


Có cách nào để làm điều này mà không có trích dẫn xung quanh "headers.From" không?
phân tích

Tôi không biết, chỉ tự hỏi, và nghĩ rằng đôi khi nó có thể hữu ích.
phân ly

3
@trysis - Trong thực tế, tôi đã thấy rằng việc khai báo các đối tượng nội tuyến (như các ví dụ trong tài liệu mongo [ose] và trong hầu hết các ví dụ ngoài đó) đơn giản là không đủ trong thế giới thực. Tôi đã phát triển thói quen tạo các đối tượng 'điều kiện' và 'trường' mà tôi có thể thực hiện những thứ như conditions['some.path'] = 'value'trong logic kinh doanh của mình, sau đó chạy một truy vấn duy nhất ở cuối:find(conditions, fields, callback);
Ryan Wheale

Điều gì sẽ xảy ra nếu chúng ta nói rằng tôi có một khóa chứa "domain.com", điều này sẽ không hoạt động : domains.domain.com. Có cách giải quyết nào cho kịch bản này (mà không thay đổi domain.com thành một cái gì khác không, ví dụ domain_com)?
Rens Tillmann

1
Trả lời nhận xét của riêng tôi, tốt nhất là tránh sử dụng dấu chấm hoàn toàn trong các phím của bạn. Trong giải pháp của mình, tôi đã bỏ hoàn toàn các tên miền thành các khóa và thay vào đó tạo ra một lát / mảng.
Rens Tillmann

20

Hai cơ chế truy vấn hoạt động theo những cách khác nhau, như được đề xuất trong các tài liệu ở phần Subdocument :

Khi lĩnh vực này nắm giữ một tài liệu nhúng (ví dụ, subdocument ), bạn có thể chỉ định toàn bộ subdocument như giá trị của một trường, hoặc “tầm thành” các subdocument sử dụng ký hiệu dấu chấm, để xác định giá trị cho các lĩnh vực cá nhân trong subdocument :

Công bằng khớp trong các tài liệu con chọn tài liệu nếu văn bản con khớp chính xác với văn bản con được chỉ định, bao gồm cả thứ tự trường.


Trong ví dụ sau, truy vấn khớp với tất cả các tài liệu trong đó giá trị của nhà sản xuất trường là một văn bản con chỉ chứa trường companycó giá trị 'ABC123'và trường addresscó giá trị '123 Street', theo thứ tự chính xác:

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

8
Tôi phát điên Điều này đối với tôi khá không nhất quán, bởi vì khi truy vấn các đối tượng, các thuộc tính trực tiếp có thể được khớp theo bất kỳ thứ tự nào.
Capaj

7

Vì có rất nhiều nhầm lẫn về truy vấn Bộ sưu tập MongoDB với các tài liệu phụ , tôi nghĩ rằng giá trị của nó để giải thích các câu trả lời ở trên với các ví dụ:

Đầu tiên tôi chỉ chèn hai đối tượng trong bộ sưu tập là: messageas:

> 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"
    }
}
>

Vì vậy, kết quả của truy vấn là gì: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

Nó phải là một bởi vì các truy vấn này cho các tài liệu có headerscùng đối tượng {From: "reservations@marriott.com"}, chỉ có nghĩa là không chứa các trường khác hoặc chúng ta nên chỉ định toàn bộ tài liệu phụ là giá trị của một trường.

Vì vậy, theo câu trả lời từ @ Edmondo1984

Công bằng khớp trong tài liệu phụ chọn tài liệu nếu tài liệu con khớp chính xác với tài liệu phụ được chỉ định, bao gồm cả thứ tự trường .

Từ các câu trên, kết quả truy vấn dưới đây là gì?

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

Và nếu chúng ta sẽ thay đổi thứ tự FromTonghĩa là giống như tài liệu phụ của tài liệu thứ hai thì sao?

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

vì vậy, nó khớp chính xác với tài liệu con được chỉ định, bao gồm cả thứ tự trường .

Đối với việc sử dụng toán tử chấm, tôi nghĩ rằng nó rất rõ ràng cho mọi người. Hãy xem kết quả của truy vấn dưới đây:

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

Tôi hy vọng những giải thích này với ví dụ trên sẽ giúp ai đó rõ ràng hơn trong việc tìm kiếm truy vấn với các tài liệu phụ .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.