MongoDB中的日期对象与Mongoose和Nodejs聚合

时间:2014-04-11 13:13:55

标签: node.js mongodb mongoose aggregation-framework isodate

我正在尝试使用mongoose对来自nodejs的聚合中的Date对象进行操作。我的DB文档具有以下形式:

{"__v" : 0,
"dob" : ISODate("1991-04-10T11:41:02.361Z"),
"gender" : "MALE",
...}

我正在尝试如下计算当前年龄,这在robomongo和shell中工作正常

db.p.aggregate([
{$project: { "age": {$divide: [{ $subtract: [ new ISODate(),  "$dob"  ] },31558464000]}}}
])

输出:

"result" : [ 
    {
        "age" : 23.00286577030492,
        "gender" : "MALE"
    }, 
    ...
]

但我无法从猫鼬内部开始工作。如果我使用相同的查询,则ISODate未定义如下:ISODate is not defined

所以我建议尝试不同的Date()

变体
{$project: { "age": {$divide: [{ $subtract: [ new Date(),  "$dob"  ] }, 31558464000] }}}
RESULT: [MongoError: exception: cant $subtract a String from a Date]

{$project: {
   "age": {$divide: [{ $subtract: [ new Date(),  new Date("$dob")  ] }, 31558464000] },
   "dob2": { $subtract: [ new Date("$dob"), 1  ]  }, "dob": 1}}
RESULT: [ { _id: '10000000000000000000000b',
dob: '1991-04-10T11:41:02.361Z',
age: 44.27401739168928,                          <-- wrong age
dob2: Thu Jan 01 1970 00:59:59 GMT+0100 (CET) }, <-- wrong date
... ]

 {$project: {
   "age": {$divide: [{ $subtract: [ new Date(),  Date("$dob")  ] }, 31558464000] },
   "dob": 1}}
 RESULT: [MongoError: exception: cant $subtract a String from a Date]

如果我尝试将String转换为聚合中的日期,则无法正确转换但在聚合之外它可以正常工作:

var dateISOString = "1991-04-10T11:41:02.361Z";
var dateTimeDate = new Date(startTimeISOString);
RESULT: Wed Apr 10 1991 13:41:02 GMT+0200 (CEST) 23.00290412198135  <-- correct Date

所以我不能使用直接引用$ dob,因为它被视为String。我不能使用ISODate转换,因为它没有定义,我不能使用新的Date(),因为转换在聚合框架中是错误的。我已广泛搜索,但无法找到问题的解决方案。如何将我的ISODate字符串转换为正确的日期或直接在第一个地方获取日期,而不是聚合。非常感谢帮助。

MongoDB: "version" : "2.4.9",
"sysInfo" : "Linux SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_49",

nodejs: v0.10.21

在Neil的回复后编辑:

     function test( user, callback ) {
        var mongoose = require( 'mongoose' );

        mongoose.connect( 'mongodb://localhost:8080/11', function( ) {  } );


            var
                collection;
            if( err ) {
                callback( err );
            } else {
                collection = mongoose.connections[0].collection( 'aggregate' );

                        collection.aggregate([
                            { "$project": {
                                "_id": 0,
                                "this": { "$divide": [
                                    { "$subtract": [ new Date(), "$dob" ]},
                                    31558464000
                                ]}
                            }}
                        ], function( err, res ) {
                            console.warn( 'collection.doneCb.1', res, JSON.stringify( res ) );
                            callback( err, res );
                        } );

                        /*collection.aggregate( query, function( err, res ) {
                         console.warn( 'collection.doneCb.1', res, JSON.stringify( res ) );
                         callback( err, res );
                         } );*/
                    } );

                } );

            }

};

这会产生:

{ [MongoError: exception: cant $subtract a String from a Date]
name: 'MongoError',
errmsg: 'exception: cant $subtract a String from a Date',
code: 16613,
ok: 0 }

谢谢!

1 个答案:

答案 0 :(得分:1)

所以只是为了澄清输出。 ISODate是MongoDB shell的内部函数,或者在驱动程序函数中提供。但是对于JavaScript,只需使用Date()对象构造函数:

鉴于数据:

{ "date" : ISODate("1971-09-22T00:00:00Z") }

以下查询:

db.birthdays.aggregate([
    { "$project": { 
        "_id": 0,
        "this": { "$divide": [
            { "$subtract": [ new Date(), "$date" ]}, 
            31558464000 
        ]} 
    }}
])

产地:

{ "this" : 42.552055734461604 }

即使我很抱歉这样说; - )