Đối với MongoDB 3.6 và mới hơn:
$expr
toán tử cho phép sử dụng các biểu thức tổng hợp trong ngôn ngữ truy vấn, do đó bạn có thể tận dụng việc sử dụng $dateToString
toán tử để chuyển đổi trường ngày:
db.test.find({
"$expr": {
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
}
})
hoặc sử dụng khung tổng hợp với $match
đường ống
db.test.aggregate([
{ "$match": {
"$expr": {
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
}
} }
])
Đối với MongoDB 3.0+:
Bạn cũng có thể sử dụng khung tổng hợp với $redact
toán tử đường ống cho phép bạn xử lý điều kiện logic với $cond
và sử dụng các phép toán đặc biệt $$KEEP
để "giữ" tài liệu có điều kiện logic đúng hoặc $$PRUNE
để "xóa" tài liệu có điều kiện sai.
Hãy xem xét việc chạy hoạt động tổng hợp sau đây để thể hiện khái niệm trên:
db.test.aggregate([
{
"$redact": {
"$cond": [
{
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
Thao tác này tương tự như có $project
đường ống chọn các trường trong bộ sưu tập và tạo một trường mới chứa kết quả từ truy vấn điều kiện logic và sau đó là $match
, ngoại trừ $redact
sử dụng một giai đoạn đường ống duy nhất hiệu quả hơn:
db.test.aggregate([
{
"$project": {
"created": 1,
"last_active": 1,
"sameDay": {
"$cond": [
{
"$eq": [
{"$substr" : ["$last_active",0, 10]},
{"$substr" : ["$created",0, 10]}
]
}, true, false
]
}
}
},
{ "$match": { "sameDay": false } }
])
0r
db.test.aggregate([
{
"$project": {
"created": 1,
"last_active": 1,
"sameDay": {
"$cond": [
{
"$eq": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
}, true, false
]
}
}
},
{ "$match": { "sameDay": false } }
])
Một cách tiếp cận khác là sử dụng $where
toán tử trong find()
của bạn nhưng lưu ý rằng truy vấn sẽ khá chậm vì sử dụng $where
Riêng yêu cầu quét bảng và cơ sở dữ liệu thực thi biểu thức hoặc hàm JavaScript cho mỗi tài liệu trong bộ sưu tập, vì vậy hãy kết hợp với các truy vấn được lập chỉ mục nếu bạn có thể vì hiệu suất truy vấn cũng được cải thiện khi bạn thể hiện nó bằng các toán tử MongoDB chuẩn (ví dụ: $gt
, $in
):
db.test.find({
"$where": function() {
return this.created.getDate() !== this.last_active.getDate()
}
});
hoặc nhỏ gọn hơn:
db.test.find({ "$where": "this.created.getDate() !== this.last_active.getDate()" });
Với đầu vào:
/* 0 */
{
"_id" : 1,
"created" : ISODate("2014-12-19T06:01:17.171Z"),
"last_active" : ISODate("2014-12-21T15:38:13.842Z")
}
/* 1 */
{
"_id" : 2,
"created" : ISODate("2015-07-06T12:17:32.084Z"),
"last_active" : ISODate("2015-07-06T18:07:08.145Z")
}
/* 2 */
{
"_id" : 3,
"created" : ISODate("2015-07-06T06:01:17.171Z"),
"last_active" : ISODate("2015-07-07T10:04:30.921Z")
}
/* 3 */
{
"_id" : 4,
"created" : ISODate("2015-07-06T06:01:17.171Z"),
"last_active" : ISODate("2015-07-06T09:47:44.186Z")
}
/* 4 */
{
"_id" : 5,
"created" : ISODate("2013-12-19T06:01:17.171Z"),
"last_active" : ISODate("2014-01-20T13:21:37.427Z")
}
Tổng hợp trả về:
/* 0 */
{
"result" : [
{
"_id" : 1,
"created" : ISODate("2014-12-19T06:01:17.171Z"),
"last_active" : ISODate("2014-12-21T15:38:13.842Z"),
"sameDay" : false
},
{
"_id" : 3,
"created" : ISODate("2015-07-06T06:01:17.171Z"),
"last_active" : ISODate("2015-07-07T10:04:30.921Z"),
"sameDay" : false
},
{
"_id" : 5,
"created" : ISODate("2013-12-19T06:01:17.171Z"),
"last_active" : ISODate("2014-01-20T13:21:37.427Z"),
"sameDay" : false
}
],
"ok" : 1
}