我有包含last_active日期和创建日期的mongo文档。我想搜索last_active的天不等于创建的天的所有文档,但我不知道如何编写查询。
在MySQL中,我会这样写:
WHERE DATE_FORMAT(created, '%Y-%m-%d') != DATE_FORMAT(last_active, '%Y-%m-%d')
答案 0 :(得分:3)
对于MongoDB 3.6及更高版本:
$expr
运算符允许在查询语言中使用聚合表达式,因此您可以利用 $dateToString
运算符进行转换日期字段:
db.test.find({
"$expr": {
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
}
})
或使用聚合框架与 $match
管道
db.test.aggregate([
{ "$match": {
"$expr": {
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
}
} }
])
对于MongoDB 3.0 +:
您还可以将聚合框架与 $redact
管道运算符一起使用,该运算符允许您使用 $cond
运算符处理逻辑条件,使用特殊操作 $$KEEP
来"保持"逻辑条件为真的文档或 $$PRUNE
到"删除"条件错误的文件。
考虑运行以下聚合操作,该操作演示了上述概念:
db.test.aggregate([
{
"$redact": {
"$cond": [
{
"$ne": [
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } },
{ "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
此操作类似于具有 $project
管道,该管道选择集合中的字段并创建一个新字段,其中包含逻辑条件查询的结果,然后是后续的 $match
,但 $redact
使用更高效的单个管道阶段:
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 } }
])
另一种方法是在 find()
方法中使用 $where
运算符,但请注意,由于使用< strong> $where
单独需要进行表扫描,并且数据库为集合中的每个文档执行JavaScript表达式或函数,因此如果可以,那么当您使用表达式查询时,查询性能也会提高标准的MongoDB运算符(例如, $gt
, $in
):
db.test.find({
"$where": function() {
return this.created.getDate() !== this.last_active.getDate()
}
});
或更紧凑:
db.test.find({ "$where": "this.created.getDate() !== this.last_active.getDate()" });
输入:
/* 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")
}
聚合返回:
/* 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
}
答案 1 :(得分:0)
在mongo聚合中使用$cond找出created != last_active
检查以下聚合:
db.collectionName.aggregate([
{
"$project": {
"check": {
"$cond": {
"if": {
"$ne": [
"$created",
"$last_active"
]
},
"then": 1,
"else": 0
}
},
"all": "$$ROOT"
}
},
{
"$match": {
"check": 1
}
},
{
"$project": {
"_id": 0,
"all": 1
}
}
]).pretty()
答案 2 :(得分:0)
执行此操作的一种方法是使用$ http://docs.mongodb.org/manual/reference/operator/query/where/ 或者您可以使用聚合查询。像这样的东西(改进以添加你需要检索的字段):
db.dates.aggregate({$project: { created: 1, last_active: 1, are_diff: {$ne: ["$created", "$last_active"]}}}, {$match: {are_diff: true}})
答案 3 :(得分:0)
您可以在查询中使用某个功能:
db.mycollection.find({
$where: function() {
return this.created.getDate() !== this.last_active.getDate();
}
})