gpt4 book ai didi

MongoDb:如何对日期字段进行聚合、分组和排序?

转载 作者:行者123 更新时间:2023-12-03 00:49:31 26 4
gpt4 key购买 nike

在我的 MongoDB 人员集合中,我需要过滤具有相同“别名”属性值的人员,保留其中第一个,并保留所有具有空“别名”的人员。

数据是这样的:

{ "_id" : "1", "flag" : true,  "name" : "Alice",    "alias" : null, "dateOfBirth": new ISODate('1995-12-27T00:00:00.000Z') },
{ "_id" : "2", "flag" : true, "name" : "Bob", "alias" : "4c", "dateOfBirth": new ISODate('1996-12-27T00:00:00.000Z') },
{ "_id" : "3", "flag" : true, "name" : "Bobby", "alias" : "4c", "dateOfBirth": new ISODate('1997-12-27T00:00:00.000Z') },
{ "_id" : "4", "flag" : true, "name" : "Cristina", "alias" : null, "dateOfBirth": new ISODate('1998-12-27T00:00:00.000Z') },
{ "_id" : "5", "flag" : false, "name" : "Diego", "alias" : null, "dateOfBirth": new ISODate('1999-12-27T00:00:00.000Z') },
{ "_id" : "6", "flag" : true, "name" : "Zoe", "alias" : "22", "dateOfBirth": new ISODate('2000-12-27T00:00:00.000Z') }

这是我的查询:

db.people.aggregate([ 
{ '$match': { 'flag': true } },
{ '$project': {
'name': 1,
'alias': {
'$cond': [
{ '$eq': [ '$alias', null ] },
'$_id',
'$alias'
]
}
}},
{ '$group': {
'_id': '$alias',
'name': { '$first': '$name' },
'id': { '$first': '$_id' }
}},
{ '$project': {
'alias': {
'$cond': [
{ '$eq': [ '$id', '$_id' ] },
null,
'$_id'
]
},
'name': 1,
'_id': '$id'
}}
])

返回结果:

{ "_id" : "6", "name" : "Zoe",      "alias" : "22" }
{ "_id" : "4", "name" : "Cristina", "alias" : null }
{ "_id" : "2", "name" : "Bob", "alias" : "4c" }
{ "_id" : "1", "name" : "Alice", "alias" : null }

到目前为止一切顺利。

更新:到目前为止,问题类似于 suggested duplicate question 。现在是不同的部分:

我需要根据“dateOfBirth”字段对其进行排序。
非常有信心,我将查询更改为:

db.people.aggregate([ 
{ '$match': { 'flag': true } },
{ '$project': {
'name': 1,
'dateOfBirth': 1,
'alias': {
'$cond': [
{ '$eq': [ '$alias', null ] },
'$_id',
'$alias'
]
}
}},
{ '$group': {
'_id': '$alias',
'name': { '$first': '$name' },
'dateOfBirth': { '$first': '$dateOfBirth' },
'id': { '$first': '$_id' }
}},
{ '$project': {
'alias': {
'$cond': [
{ '$eq': [ '$id', '$_id' ] },
null,
'$_id'
]
},
'name': 1,
'_id': '$id',
'dateOfBirth': 1,
}},
{ '$sort': { 'dateOfBirth': 1 }}
])

但这给出了:

{ "_id" : "1", "name" : "Alice",    "dateOfBirth" : ISODate("1995-12-27T00:00:00Z"), "alias" : null }
{ "_id" : "6", "name" : "Zoe", "dateOfBirth" : null, "alias" : "22" }
{ "_id" : "4", "name" : "Cristina", "dateOfBirth" : null, "alias" : null }
{ "_id" : "2", "name" : "Bob", "dateOfBirth" : null, "alias" : "4c" }

当然,这是错误的:dateOfBirth 字段未通过 $group 阶段...

有什么线索可以让它通过吗?

最佳答案

实际上,这对我来说效果很好,我怀疑您正在运行的实际代码(不是该列表)中有一个拼写错误,缺少在某处包含“dateOfBirth”(或者可能拼写错误)。

但如果说这里有一个教训的话,那就应该是不要分开 $project$group阶段,因为引入另一个管道阶段不仅效率低下(这意味着额外传递数据),而且在指定要包含在管道中的数据时,这也是造成困惑的常见原因。

所以宁愿这样做:

db.people.aggregate([
{ "$match": { "flag": true } },
{ "$group": {
"_id": {
"$ifNull": [ "$alias", "$_id" ]
},
"name": { "$first": "$name" },
"dateOfBirth": { "$first": "$dateOfBirth" },
"id": { "$first": "$_id" }
}},
{ "$project": {
"_id": "$id",
"name": 1,
"dateOfBirth": 1,
"alias": {
"$cond": [
{ "$eq": [ "$_id", "$id" ] },
null,
"$_id"
]
}
}},
{ "$sort": { "dateOfBirth": 1 } }
])

这也利用 $ifNull作为自然测试,而不是在不需要时使用 $cond

当然会返回所需的结果:

{ "_id" : "1", "name" : "Alice", "dateOfBirth" : ISODate("1995-12-27T00:00:00Z"), "alias" : null }
{ "_id" : "2", "name" : "Bob", "dateOfBirth" : ISODate("1996-12-27T00:00:00Z"), "alias" : "4c" }
{ "_id" : "4", "name" : "Cristina", "dateOfBirth" : ISODate("1998-12-27T00:00:00Z"), "alias" : null }
{ "_id" : "6", "name" : "Zoe", "dateOfBirth" : ISODate("2000-12-27T00:00:00Z"), "alias" : "22" }

如果您想要“按出生日期排序”,请将排序移到 $group 阶段之前,$first 运算符将在那里完成所有工作。

关于MongoDb:如何对日期字段进行聚合、分组和排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34517753/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com