2

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

{"__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

因此,按照建议,我尝试了 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]

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

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 因为它被视为字符串。我不能使用 ISODate 转换,因为它没有定义并且我不能使用 new 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

尼尔回复后编辑:

     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 }

谢谢!

4

1 回答 1

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 }

尽管我很抱歉这么说;-)

于 2014-04-11T13:33:29.607 回答