我有两个系列:
'DBVisit_DB':
"_id" : ObjectId("582bc54958f2245b05b455c6"),
"visitEnd" : NumberLong(1479252157766),
"visitStart" : NumberLong(1479249815749),
"fuseLocation" : {.... }
"userId" : "A926D9E4853196A98D1E4AC6006DAF00@1927cc81cfcf7a467e9d4f4ac7a1534b",
"modificationTimeInMillis" : NumberLong(1479263563107),
"objectId" : "C4B4CE9B-3AF1-42BC-891C-C8ABB0F8DC40",
"creationTime" : NumberLong(1479252167996),
"lastUserInteractionTime" : NumberLong(1479252167996)
}
'device_data':
"_id" : { "$binary" : "AN6GmE7Thi+Sd/dpLRjIilgsV/4AAAg=", "$type" : "00" },
"auditVersion" : "1.0",
"currentTime" : NumberLong(1479301118381),
"data" : {
"networkOperatorName" : "Cellcom",...
},
"timezone" : "Asia/Jerusalem",
"collectionAlias" : "DEVICE_DATA",
"shortDate" : 17121,
"userId" : "00DE86984ED3862F9277F7692D18C88A@1927cc81cfcf7a467e9d4f4ac7a1534b"
在DBVisit_DB中,我需要仅显示超过1小时的Cellcom用户的所有访问。 (visitEnd - visitStart> 1小时)。通过匹配两个集合中的userId值。 这就是我到目前为止所做的:
//create an array that contains all the rows that "Cellcom" is their networkOperatorName
var users = db.device_data.find({ "data.networkOperatorName": "Cellcom" },{ userId: 1, _id: 0}).toArray();
//create an array that contains all the rows that the visit time is more then one hour
var time = db.DBVisit_DB.find( { $where: function() {
timePassed = new Date(this.visitEnd - this.visitStart).getHours();
return timePassed > 1}},
{ userId: 1, _id: 0, "visitEnd" : 1, "visitStart":1} ).toArray();
//merge between the two arrays
var result = [];
var i, j;
for (i = 0; i < time; i++) {
for (j = 0; j < users; j++) {
if (time[i].userId == users[j].userId) {
result.push(time[i]);
}
}
}
for (var i = 0; i < result.length; i++) {
print(result[i].userId);
}
但它没有显示任何内容,尽管我确信在我创建的数组中都可以找到id。 *用于验证:我不是100%确定我正确计算了访问时间。 顺便说一下,我是javaScript和mongodb的新手
********update********
{ "userId" : "457A7A0097F83074DA5E05F7E05BEA1D@1927cc81cfcf7a467e9d4f4ac7a1534b" }
{ "userId" : "E0F5C56AC227972CFAFC9124E039F0DE@1927cc81cfcf7a467e9d4f4ac7a1534b" }
{ "userId" : "309FA12926EC3EB49EB9AE40B6078109@1927cc81cfcf7a467e9d4f4ac7a1534b" }
{ "userId" : "B10420C71798F1E8768ACCF3B5E378D0@1927cc81cfcf7a467e9d4f4ac7a1534b" }
{ "userId" : "EE5C11AD6BFBC9644AF3C742097C531C@1927cc81cfcf7a467e9d4f4ac7a1534b" }
{ "userId" : "20EA1468672EFA6793A02149623DA2C4@1927cc81cfcf7a467e9d4f4ac7a1534b" }
每个数组都包含这种格式,在我的查询之后,我需要将它们合并为一个。我会有他们之间的交集。
非常感谢所有的帮助!
答案 0 :(得分:1)
使用聚合框架,您可以通过使用 $lookup
运算符来实现所需的结果,该运算符允许您执行&#34; left-join&#34;对同一数据库中的集合进行操作,并利用 $redact
管道运算符,该运算符可以容纳操作时间戳的算术运算符,并将它们转换为可以查询的分钟数。
要显示上述聚合运算符的实用程度的简单示例,您可以在DBVisit_DB
集合上运行以下管道,以分钟为单位查看实际时差:
db..getCollection('DBVisit_DB').aggregate([
{
"$project": {
"visitStart": { "$add": [ "$visitStart", new Date(0) ] },
"visitEnd": { "$add": [ "$visitEnd", new Date(0) ] },
"timeDiffInMinutes": {
"$divide": [
{ "$subtract": ["$visitEnd", "$visitStart"] },
1000 * 60
]
},
"isMoreThanHour": {
"$gt": [
{
"$divide": [
{ "$subtract": ["$visitEnd", "$visitStart"] },
1000 * 60
]
}, 60
]
}
}
}
])
示例输出
{
"_id" : ObjectId("582bc54958f2245b05b455c6"),
"visitEnd" : ISODate("2016-11-15T23:22:37.766Z"),
"visitStart" : ISODate("2016-11-15T22:43:35.749Z"),
"timeDiffInMinutes" : 39.0336166666667,
"isMoreThanHour" : false
}
现在,了解上述运算符的工作原理,现在可以在以下示例中应用它,其中运行以下聚合管道将使用device_data
集合作为主集合,首先过滤文档使用 $match
指定字段,然后使用 $lookup
加入DBVisit_DB
集合。 $redact
将处理在 $cond
内获取超过一小时的访问的逻辑条件,并使用特殊系统变量 { {3}} to&#34; keep&#34;逻辑条件为真的文档或 $$KEEP
到&#34; discard&#34;条件错误的文件。
算术运算符 $$PRUNE
和 $divide
允许您计算两个时间戳字段之间的差异,以及 $subtract
逻辑运算符然后评估条件:
db.device_data.aggregate([
/* Filter input documents */
{ "$match": { "data.networkOperatorName": "Cellcom" } },
/* Do a left-join to DBVisit_DB collection */
{
"$lookup": {
"from": "DBVisit_DB",
"localField": "userId",
"foreignField": "userId",
"as": "userVisits"
}
},
/* Flatten resulting array */
{ "$unwind": "$userVisits" },
/* Redact documents */
{
"$redact": {
"$cond": [
{
"$gt": [
{
"$divide": [
{ "$subtract": [
"$userVisits.visitEnd",
"$userVisits.visitStart"
] },
1000 * 60
]
},
60
]
},
"$$KEEP",
"$$PRUNE"
]
}
}
])
答案 1 :(得分:1)
您的java脚本中有一些不正确的东西。
在time
循环中将users
和time.length
条件替换为users.length
和for
。
您的timePassed
计算应为
timePassed = this.visitEnd - this.visitStart
return timePassed > 3600000
您有几个与数据相关的问题。
您没有匹配的userId
,visitEnd
和visitStart
之间的差异不到一小时,您在问题中发布的文件就不会有。
对于基于mongo的查询,您应该结帐其他answer。