2013-04-25 30 views
30

Tôi đang cố gắng tìm tất cả tài liệu không chứa ít nhất một tài liệu có giá trị trường cụ thể. Ví dụ ở đây là một bộ sưu tập mẫu:Tìm tài liệu có mảng không chứa tài liệu có giá trị trường cụ thể trong MongoDB

{ _id : 1, 
    docs : [ 
     { foo : 1, 
      bar : 2}, 
     { foo : 3, 
      bar : 3} 
     ] 
}, 
{ _id : 2, 
    docs : [ 
     { foo : 2, 
      bar : 2}, 
     { foo : 3, 
      bar : 3} 
     ] 
} 

Tôi muốn tìm tất cả các kỷ lục mà không có một tài liệu trong khối tài liệu mà không có ít nhất một kỷ lục với foo = 1. Trong ví dụ trên chỉ, tài liệu thứ hai sẽ được trả về.

Tôi đã thử những điều sau đây, nhưng nó chỉ nói với tôi nếu có bất kỳ không phù hợp (trong đó trả về tài liệu 1.

db.collection.find({"docs": { $not: {$elemMatch: {foo: 1 } } } }) 

UPDATE: Các truy vấn trên thực sự làm việc Như nhiều. lần này, dữ liệu của tôi sai, không phải mã của tôi

Tôi cũng đã xem $nin operator nhưng các ví dụ chỉ hiển thị khi mảng chứa danh sách các giá trị nguyên thủy chứ không phải tài liệu bổ sung. điều này với một cái gì đó như sau, nó tìm kiếm các tài liệu chính xác hơn là ju st lĩnh vực foo tôi muốn.

db.collection.find({"docs": { $nin: {'foo':1 } } }) 

Có cách nào để thực hiện việc này với các toán tử cơ bản không?

Trả lời

38

Sử dụng $nin sẽ hoạt động nhưng bạn đã sai cú pháp. Nó nên là:

db.collection.find({'docs.foo': {$nin: [1]}}) 
+4

Tò mò, tại sao '$ nin' thay vì' $ ne'? Bạn không thể làm 'db.collection.find ({'docs.foo': {$ ne: 1}})'? (tức là cùng một điều nhưng không cần 1 để được trong một mảng, như trong [aedm của câu trả lời] (http://stackoverflow.com/a/38684656/3391108)) – tscizzle

+1

@tscizzle Yep, '$ ne' là tốt như tốt nếu chỉ có một giá trị. – JohnnyHK

+0

'$ ne' cũng sẽ hiệu quả hơn một chút (nhanh hơn) – ztrange

11

Sử dụng các nhà điều hành $ne:

db.collection.find({'docs.foo': {$ne: 1}}) 

Cập nhật: tôi muốn khuyên bạn không dùng $nin trong trường hợp này.

{'docs.foo': {$ne: 1}} lấy tất cả các phần tử của docs và mỗi phần tử sẽ kiểm tra xem trường foo có bằng 1 hay không. Nếu nó tìm thấy một kết quả phù hợp, nó sẽ loại bỏ tài liệu khỏi danh sách kết quả.

{'docs.foo': {$nin: [1]}} lấy tất cả các thành phần của docs và đối với mỗi phần tử, nó kiểm tra xem trường foo có khớp với bất kỳ thành viên nào của mảng [1] hay không. Đây là Cartesian product, bạn so sánh mảng với mảng khác, mỗi phần tử cho từng phần tử. Mặc dù MongoDB có thể thông minh và tối ưu hóa truy vấn này, tôi cho rằng bạn chỉ sử dụng $nin vì "nó đã làm gì đó với mảng". Nhưng nếu bạn hiểu những gì bạn làm ở đây, bạn sẽ nhận ra $nin là không cần thiết và có thể có hiệu suất phụ.

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