如何解决如何在不使用$ unwind的情况下加快包括数组中日期字符串比较在内的聚合查询?
我有一个集合,其中包含带有嵌套数组的文档。 subfield
数组中有100万个文档,其中包含数千个对象。文档很大,但是出于解释目的,请考虑以下两个文档:
[
{
"id": "myid","field": {
"total": 1,"subfield": [
{
"somefield": "1000","time": "2020-08-06T08:33:57.977+0530","val": [
{
"x": "someval","a": "val1","b": "val2"
}
]
},{
"somefield": "2000","time": "2020-05-08T04:13:27.977+0530","val": [
{
"x": "someval2","b": "val2"
}
]
}
]
}
},{
"id": "myid2","subfield": [
{
"somefield": "1001","time": "2020-07-31T10:15:50.184+0530","b": "val2"
},{
"x": "someval2","b": "val2"
}
]
}
]
}
}
]
用例:
我只需要投影id
日期(按日期分组)大于某个值且time
或field. subfield.val.b
具有特定值的文档field. subfield.val.a
。 / p>
我有查询要使用$unwind
,$toDate
,$dateToString
运算符来实现用例。
但是对于大型数组使用$unwind
会导致整个集合使用大量内存并减慢速度。现在要花费超过15分钟的时间。(我没有添加任何索引,因为即使我为created
创建索引,当我运行解释汇总时,获胜查询也不使用提供的索引)
我当前的查询:
db.collection.aggregate([
{
$unwind: {
path: "$field.subfield",}
},{
$unwind: {
path: "$field.subfield.val",{
$addFields: {
created_at: {
$toDate: "$field.subfield.time"
}
}
},{
$match: {
$and: [
{
$expr: {
$gt: [
{
"$dateToString": {
"date": "$created_at","format": "%Y-%m-%d"
}
},"2020-04-28"
]
}
},{
$or: [
{
"field.subfield.val.a": {
"$eq": "val1"
}
},{
"field.subfield.val.b": {
"$eq": "val1"
}
}
]
}
]
}
},{
$group: {
_id: "$id"
}
}
])
我需要将查询的执行时间限制为少于30秒。我希望,如果不使用$unwind
,可以更快地完成此过程。
我的MongoDB服务器版本为4.0.3
还可以进行其他哪些优化?
谢谢!
解决方法
您尝试过$ elemMatch吗?它的工作原理实际上类似于js函数Array.some()
https://docs.mongodb.com/manual/reference/operator/query/elemMatch/下的更多信息
{
$match:{
histories:{
$elemMatch:{
created_at:{
$gt:'2020-04-28'
}
}
}
}
}
,
可以进行的可能的优化:
- 由于
$unwind
降低了查询速度,因此$filter
可用于从嵌套数组中获取匹配结果。 - 日期字符串比较繁琐,因此最好将日期存储为MongoDB日期对象,并使用日期类型本身(而不是日期字符串类型)进行所有比较。
db.collection.aggregate([
{
"$project": {
"obj1": {
"$filter": {
"input": "$field.subfield","as": "el","cond": {
"$and": [
{
"$gt": [
"$$el.time",new Date("2020-04-29")
]
}
]
}
}
},id: 1,}
},{
$match: {
$or: [
{
"obj1.val.a": {
"$eq": "val1"
}
},{
"obj1.val.b": {
"$eq": "val1"
}
}
]
}
},{
$project: {
id: 1,_id: 0
}
}
])
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。