【发布时间】:2021-06-27 08:23:17
【问题描述】:
我正在尝试计算两个文档之间的时间差,但我不确定如何根据数组中是否存在值来执行此操作。
让我更详细地解释一下。假设我有五个文档:A, B, C, D, E 在一个集合中。
每个文档都有referenceKey、timestamp 和persons 字段。 persons 数组中的每个元素都有 personType 字段以及其他字段:
A: { referenceKey: 1, timestamp: ISODate, persons: [ { personType: "ALICE", ... }, { personType: "BOB", ... } ] }
B: { referenceKey: 1, timestamp: ISODate, persons: [ { personType: "ALICE", ... }, { personType: "BOB", ... } ] }
C: { referenceKey: 1, timestamp: ISODate, persons: [ { personType: "BOB", ... } ] }
D: { referenceKey: 1, timestamp: ISODate, persons: [ { personType: "ALICE", ... }, { personType: "BOB", ... } ] }
E: { referenceKey: 1, timestamp: ISODate, persons: [ { personType: "BOB", ... } ] }
我想要实现的是计算类型为ALICE 的人每次访问花费了多少时间。
换句话说,这应该计算并返回一个时间差数组:
[{ timeSpent: C.timestamp - A.timestamp }, { timeSpent: E.timestamp - D.timestamp }]
这是一个要测试的示例集合:
[
{
timestamp: ISODate("2019-04-12T20:00:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
},
{
personType: "ALICE"
}
]
},
{
timestamp: ISODate("2019-04-12T20:10:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
}
]
},
{
timestamp: ISODate("2019-04-12T21:00:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
},
{
personType: "ALICE"
}
]
},
{
timestamp: ISODate("2019-04-12T21:15:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
}
]
},
{
timestamp: ISODate("2019-04-12T21:20:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
}
]
},
{
timestamp: ISODate("2019-04-12T21:45:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
},
{
personType: "ALICE"
}
]
},
{
timestamp: ISODate("2019-04-12T22:05:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
},
{
personType: "ALICE"
}
]
},
{
timestamp: ISODate("2019-04-12T23:00:00.000Z"),
referenceKey: 1,
persons: [
{
personType: "BOB"
}
]
},
{
timestamp: ISODate("2019-04-12T18:30:00.000Z"),
referenceKey: 2,
persons: [
{
personType: "BOB"
},
{
personType: "JOHN"
}
]
}
]
我想我可以基于人员类型ALICE 的存在使用$in 添加一个新的布尔字段hasAlice。但问题是应该为每次访问计算花费的时间,所以我不能只使用$reduce 来计算总时间。我可以通过hasAlice字段更改以某种方式使用$group,然后使用$reduce吗?
到目前为止我已经尝试过(但失败了):
db.collection.aggregate([
{
"$match": { // I also filter by timestamp and referenceKey but it is not relevant to the problem
timestamp: {
"$gte": ISODate("2019-04-12T00:00:00.000Z"),
"$lt": ISODate("2019-04-12T23:59:00.000Z")
},
referenceKey: 1
}
},
{
"$project": {
_id: 0,
timestamp: 1,
hasAlice: {
"$in": [
"ALICE",
"$persons.personType"
]
}
}
},
{
"$sort": {
timestamp: 1
}
}
])
我想得到什么:
[
{ timeSpent: 10 }, // in minutes
{ timeSpent: 15 },
{ timeSpent: 75 },
]
我在运行聚合时实际得到的结果:
[
{
"hasAlice": true, // 1. visit starts
"timestamp": ISODate("2019-04-12T20:00:00Z")
},
{
"hasAlice": false, // 1. visit ends
"timestamp": ISODate("2019-04-12T20:10:00Z")
},
{
"hasAlice": true, // 2. visit starts
"timestamp": ISODate("2019-04-12T21:00:00Z")
},
{
"hasAlice": false, // 2. visit ends
"timestamp": ISODate("2019-04-12T21:15:00Z")
},
{
"hasAlice": false,
"timestamp": ISODate("2019-04-12T21:20:00Z")
},
{
"hasAlice": true, // 3. visit starts
"timestamp": ISODate("2019-04-12T21:45:00Z")
},
{
"hasAlice": true, // NOTE: there are some misleading documents such as these (e.g. document B)
"timestamp": ISODate("2019-04-12T22:05:00Z")
},
{
"hasAlice": false, // 3. visit ends
"timestamp": ISODate("2019-04-12T23:00:00Z")
}
]
我不知道我的逻辑是否正确,或者我能否以某种方式减少这些文档来计算每次访问所花费的时间。但任何帮助表示赞赏。 提前致谢。
【问题讨论】:
标签: mongodb mongodb-query aggregation-framework