聚合查询调整时区的日期

时间:2015-08-31 11:42:18

标签: java mongodb mongodb-query aggregation-framework

我想使用java代码运行这个mongodb查询。

查询:

 public class SomeTemplateSelector : DataTemplateSelector
{
    public DataTemplate OthersTemplate { get; set; }
    public DataTemplate DefaultTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        return DefaultTemplate;
    }
}

我尝试使用此代码,但它没有用

db.log.aggregate([
    { $match : { 
        "ts" : { 
            $gte: ISODate("2015-07-31T18:30:00.000Z"),
            $lt: ISODate("2015-08-01T18:30:00.000Z")  
        },
        "dup": {$exists:false} 
    }},
    { $project : { 
        'lts': { 
            '$add': ['$ts',5.5*3600*1000]
        }
    }},
    { $group : { 
        _id : { 
            day: { $dayOfMonth: "$lts" },
            month: { $month: "$lts" },
            year: { $year: "$lts" }
        },
        count: { $sum: 1 }
    }}
])

2 个答案:

答案 0 :(得分:2)

您的初始查询可能写得更好。大概你想要按照" day"同时也从UTC调整到当地的timzezone。在这种情况下,通常最好只使用日期数学而不是混合date aggregation operators,这也意味着这里不需要$project,你可以直接去{ {3}}:

db.log.aggregate([
  { "$match": { 
      "ts": { 
        "$gte": ISODate("2015-07-31T18:30:00.000Z"),
        "$lt": ISODate("2015-08-01T18:30:00.000Z")  
      },
      "dup": { "$exists": false } 
  }},
  { "$group": {
    "_id": {
      "$add": [
        { "$subtract": [
          { "$subtract": [
            { "$add": [ "$ts", 5.5*1000*60*60 ] },
            new Date(0)
          ]},
          { "$mod": [
            { "$subtract": [
              { "$add": [ "$ts", 5.5*1000*60*60 ] },
              new Date(0)
            ]},
            1000*60*60*24
          ]}
        ]},
        new Date(0)
      ]
    },
    "count": { "$sum": 1 }
  }}
])

请注意其中的其他Date(0)语句。这是" epoch"就像你$group数字值到日期时得到Date类型一样,当你$add得到整数值时。因此,通过添加" epoch"进行纠正使所有内容再次成为Date类型。

因此"日期数学"在任何地方都被雇用,以及#34; round"到了"日":

  

(1000毫秒* 60秒* 60分钟* 24小时)

$subtract运算符计算出从当前日期值中减去的剩余部分,来到"舍入"日期。

所有这些都在$group完成并且也有效:

转换为Java只是遵循相同的缩进:

Date startdate = new DateTime(2015, 7, 31, 18, 30, 0, DateTimeZone.UTC).toDate();
Date enddate = new DateTime(2015, 8, 1, 18, 30, 0, DateTimeZone.UTC).toDate();

DBObject query = QueryBuilder.start()
        .put("ts").greaterThanEquals(startdate)
        .lessThan(enddate)
        .and("dup").exists(false).get();

DBObject match = new BasicDBObject("$match",query);


DBObject group = new BasicDBObject("$group",
  new BasicDBObject("_id",
    new BasicDBObject(
      "$add", Arrays.asList(
        new BasicDBObject(
          "$subtract", Arrays.asList(
            new BasicDBObject(
             "$subtract", Arrays.asList(
                new BasicDBObject(
                  "$add",Arrays.asList( "$ts", 5.5*1000*60*60 )
                ),
                new Date(0)
              )
            ),
            new BasicDBObject(
              "$mod", Arrays.asList(
                new BasicDBObject(
                 "$subtract", Arrays.asList(
                    new BasicDBObject(
                      "$add",Arrays.asList( "$ts", 5.5*1000*60*60 )
                    ),
                    new Date(0)
                  )
                ),
                1000*60*60*24
              )
            )
          )
        ),
        new Date(0)
      )
    )
  )
  .append("count", new BasicDBObject("$sum",1))
);


AggregationOutput output = collection.aggregate(Arrays.asList(match, group));

for ( DBObject result : output.results() ) {
    System.out.println(result);
}

另请注意您的" timezeone调整"这里假设5.5小时"落后" UTC,我希望是正确的。如果你的意思是"""或者是肯定的,然后该操作是一个"减法"而不是将UTC时间更正为天的补充。

所以一切都很好,你的分组键也是真正的Date个对象,而不是日期聚合运算符返回的复合值。

答案 1 :(得分:0)

将字段ts更改为东8时区:

import socket
import os

# Standard socket stuff:
host = ''
port = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(5) 

# Loop forever, listening for requests:
while True:
    csock, caddr = sock.accept()
    print("Connection from: " + str(caddr))
    req = csock.recv(1024)  # get the request, 1kB max
    print(req)
    # Look in the first line of the request for a move command
    # A move command should be e.g. 'http://server/move?a=90'
    filename = 'static/index.html'
    f = open(filename, 'r')

    csock.sendall(str.encode("HTTP/1.0 200 OK\n",'iso-8859-1'))
    csock.sendall(str.encode('Content-Type: text/html\n', 'iso-8859-1'))
    csock.send(str.encode('\r\n'))
    # send data per line
    for l in f.readlines():
        print('Sent ', repr(l))
        csock.sendall(str.encode(""+l+"", 'iso-8859-1'))
        l = f.read(1024)
    f.close()

    csock.close()