Khung tổng hợp là lý tưởng cho như vậy. Cân nhắc chạy đường dẫn sau để có được kết quả mong muốn.
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
Đường dẫn trên sử dụng $ bộ lọc
toán tử có sẵn cho MongoDB 3.2 để tạo ra một mảng đáp ứng điều kiện đã chỉ định, tức là nó lọc các phần tử bên ngoài không đáp ứng tiêu chí. $ so khớp đầu tiên
đường ống dẫn là cần thiết để lọc ra các tài liệu đi vào đường ống tổng hợp sớm như một chiến lược tối ưu hóa đường ống.
$ size
toán tử chấp nhận một biểu thức duy nhất làm đối số sau đó cung cấp cho bạn số phần tử trong mảng kết quả, do đó bạn có số sách mong muốn của mình.
Đối với giải pháp thay thế không sử dụng $ bộ lọc
không tìm thấy toán tử trong các phiên bản trước, hãy xem xét hoạt động đường ống sau:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$setDifference": [
{
"$map": {
"input": "$books",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.year", 1990 ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
}
];
db.collection.pipeline(pipeline);
$ project
giai đoạn đường ống liên quan đến việc điều chỉnh mảng sách để bạn xóa các tài liệu không có năm 1990. Điều này có thể thực hiện được thông qua $ setDifference
và $ map
các toán tử.
$ map
về bản chất, toán tử tạo ra một trường mảng mới chứa các giá trị là kết quả của logic được đánh giá trong biểu thức con cho mỗi phần tử của mảng. $ setDifference
sau đó toán tử trả về một tập hợp với các phần tử xuất hiện trong tập hợp đầu tiên nhưng không xuất hiện trong tập hợp thứ hai; tức là thực hiện một phần bù tương đối của tập hợp thứ hai so với tập hợp đầu tiên. Trong trường hợp này, nó sẽ trả về mảng sách cuối cùng có các phần tử với năm 1990 và sau đó là $ size
tính toán số phần tử trong mảng kết quả, do đó cung cấp cho bạn số sách.
Đối với giải pháp sử dụng $ thư giãn
, hãy ghi nhớ rằng (nhờ phản hồi sâu sắc này từ @BlakesSeven trong phần nhận xét):
và như một phương sách cuối cùng, hãy chạy đường dẫn sau:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)