2015-01-13 20 views
11

Giả sử tôi có một bộ sưu tập như thế này:Mongo Query Mở Nhiều lĩnh vực Sub-Document

{ "arr" : [ { "name" : "a", "num" : 1 }, { "name" : "a", "num" : 2 } ] }, 
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "a", "num" : 2 } ] }, 
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "b", "num" : 2 } ] } 

và tôi muốn tìm tất cả các tài liệu ai là arr chứa một tiểu tài liệu với một name = "b" và num = 2.

Nếu tôi làm một truy vấn như thế này:

db.collection.find({ 
    $and: [ 
     { "arr.name": "b" }, 
     { "arr.num": 2 } 
    ] 
}); 

nó sẽ trả lại tất cả các tài liệu trong bộ sưu tập vì họ từng có một su b-tài liệu với một trong hai một name của "b" hoặc một num của 2.

Tôi cũng đã thử điều này:

db.collection.find({ 
    arr: [ 
     { "name": "b", "num": 2 } 
    ] 
}); 

mà không ném bất kỳ lỗi nào, nhưng không trả lại bất kỳ kết quả .

Làm cách nào để bạn truy vấn trên nhiều trường tài liệu phụ trong MongoDB?

Trả lời

22

Đây thực sự là điều mà nhà điều hành $elemMatch là mặc dù thường bị lạm dụng. Về cơ bản nó thực hiện các điều kiện truy vấn trên mỗi phần tử "bên trong" mảng đó. Tất cả các đối số MongoDB là một "và" hoạt động trừ khi rõ ràng gọi khác:

db.collection.find({ "arr": { "$elemMatch": { "name": "b", "num": 2 } } }) 

Có thể bạn cũng muốn "dự án" ở đây cũng như nếu bạn đang mong đợi chỉ lĩnh vực phù hợp và không rằng toàn bộ tài liệu:

db.collection.find(
    { "arr": { "$elemMatch": { "name": "b", "num": 2 } } }, 
    { "arr.$": 1 } 
) 

Cuối cùng để giải thích lý do tại sao nỗ lực thứ hai của bạn không hoạt động, truy vấn này:

db.collection.find({ 
    "arr": [ 
     { "name": "b", "num": 2 } 
    ] 
}) 

không phù hợp bất cứ điều gì vì không có việc phải làm thực tế cument nơi "arr" chứa một phần tử số ít khớp chính xác với các điều kiện của bạn.

ví dụ đầu tiên của bạn không thành ..:

db.collection.find({ 
    $and: [ 
     { "arr.name": "b" }, 
     { "arr.num": 2 } 
    ] 
}); 

Bởi vì có một số phần tử mảng đáp ứng các điều kiện và điều này không chỉ là cho rằng cả hai điều kiện áp dụng đối với cùng một nguyên tố. Đó là những gì $elemMatch bổ sung và khi bạn cần thêm một điều kiện để khớp, thì đây là nơi bạn sử dụng nó.

+1

Câu trả lời rất hữu ích và đầy đủ, xin lỗi vì không thể nâng cao gấp đôi. Cảm ơn Neil! – Moppo

Các vấn đề liên quan