Hóa ra $project không hỗ trợ $elemMatch trong tổng hợp. Trong 3. 2, họ đã giới thiệu bộ lọc, v.v., điều này dường như không giải quyết được vấn đề của tôi.
Hãy để tôi giải thích những gì tôi đang cố gắng thực hiện, giả sử tôi có các tài liệu sau trong cơ sở dữ liệu
db.test.insert[ db.test.insert[ db.test.insert[{ db.test.insert[{
{
"ad_account_id": 150,
"internal_id": 1,
"daily": [{
"timestamp": "2016-12-01",
"impressions": 5
}, {
"timestamp": "2016-12-06",
"impressions": 7
}]
}]
{
"ad_account_id": 150,
"internal_id": 2,
"daily": [{
"timestamp": "2016-12-03",
"impressions": 6
}]
}]
"ad_account_id": 150,
"internal_id": 3,
"daily": []
}]
"ad_account_id": 16,
"internal_id": 3,
"daily": []
}]
Bây giờ, giả sử người dùng truy vấn ad_account_id. 150 và lọc theo phạm vi ngày bắt đầu và ngày kết thúc là "2016-12-01" đến "2016-12-02"
Truy vấn tổng hợp của tôi đọc như thế này [bỏ qua sắp xếp, giới hạn, v.v.]
db.getCollection['test'].aggregate[{
"$match" : {
"ad_account_id" : 150,
"daily" : {
"$elemMatch" : {
"timestamp" : {
"$lte" : "2016-12-02",
"$gte" : "2016-12-01"
}
}
}
}
},
{
"$unwind" : "$daily"
},
{
"$match" : {
"daily.timestamp" : {
"$lte" : "2016-12-02",
"$gte" : "2016-12-01"
}
}
},
{
"$group" : {
"impressions" : {
"$sum" : "$daily.impressions"
},
"ad_account_id" : {
"$first" : "$ad_account_id"
},
"_id" : "$internal_id"
}
},
{
"$project" : {
"impressions" : 1,
"ga_transactions" : 1,
"ad_account_id" : 1
}
}
];
{ "_id" : 1, "impressions" : 5, "ad_account_id" : 150 }
Trong quá trình phát triển tại địa phương của chúng tôi, ban đầu có vẻ ổn. Truy vấn nhanh ngay cả với một triệu tài liệu và chúng tôi rất hài lòng.
Nhưng chúng tôi đã sớm nhận ra trường hợp sử dụng của mình, nơi chúng tôi cần hiển thị các hàng ngay cả khi dữ liệu hàng ngày không nằm giữa ngày bắt đầu và ngày kết thúc. Số lần hiển thị, v.v. trong đó có thể được biểu thị bằng 0 nhưng chúng phải được hiển thị chắc chắn
Vì vậy, **kết quả mong muốn** mà chúng tôi muốn là thế này
{ "_id" : 1, "impressions" : 5, "ad_account_id" : 150 }
{ "_id" : 2, "impressions" : 0, "ad_account_id" : 150 }
{ "_id" : 3, "impressions" : 0, "ad_account_id" : 150 }
Và tôi đã vật lộn với điều này trong vài giờ qua vì dường như tôi không thể hiểu điều này trong một truy vấn mongo. Tôi nghĩ rằng tôi sẽ giới hạn đối sánh của mình chỉ với id tài khoản quảng cáo, sau đó thực hiện dự án $ và nếu không có dữ liệu nào giữa phạm vi dữ liệu đó, tôi sẽ chỉ thêm một mục nhập mẫu vào hàng ngày với dữ liệu bắt đầu dưới dạng dấu thời gian đại loại như thế này.
{
"ad_account_id": 150,
"internal_id": 3,
"daily": [{timestamp: "2016-02-01"}]
]
Nhưng thật không may, tôi không thể làm việc này, vì trong $project bạn không thể làm $elemMatch. Những thứ mới như $filter, v.v. dường như không giải quyết được vấn đề của tôi.
Tôi cũng đã thử liên minh, và tôi nghĩ nó cũng gần như vậy
db.getCollection['test'].aggregate[
{
"$match" : {
"ad_account_id" : 150,
"daily" : {
"$elemMatch" : {
"timestamp" : {
"$lte" : "2016-12-02",
"$gte" : "2016-12-01"
}
}
}
}
},
{ "$project": {
"ad_account_id": 1,
"daily": {
"$setUnion": [
{ "$map": {
"input": "$daily",
"as": "day",
"in": {
"$cond": [
{ "$and": [
{ "$gte": [ "$day.timestamp", "2016-12-01" ] },
{ "$lte": [ "$day.timestamp", "2016-12-02" ] }
]},
"$day",
false
]
}
}},
[{"timestamp": "2016-12-01"}]
]
}
}},
{
"$unwind" : "$daily"
},
{
"$match" : {
"daily.timestamp" : {
"$lte" : "2016-12-02",
"$gte" : "2016-12-01"
}
}
},
{
"$group" : {
"impressions" : {
"$sum" : "$daily.impressions"
},
"ad_account_id" : {
"$first" : "$ad_account_id"
},
"_id" : "$internal_id"
}
},
{
"$project" : {
"impressions" : 1,
"ga_transactions" : 1,
"ad_account_id" : 1
}
}
}
Nhưng điều này đã gây ra lỗi cho tôi "" FieldPath '2016-12-01' không bắt đầu bằng $". Tò mò rằng chúng ta có thể xử lý việc này bằng tất cả các kỹ thuật khác nhau nào?