2017-10-09 48 views
0

这里我有内部test.test收集两个文件:Pymongo - 古怪的聚集行为

> db.test.find() 
{ "_id" : ObjectId("AAA"), "last_updated" : 1000, "update_interval" : 50 } 
{ "_id" : ObjectId("BBB"), "last_updated" : 1200, "update_interval" : 50 } 

我想找到应该(通过测试last_updated <= now - update_interval表达)更新文件。

首先,我试图用Python pymongo如下:

from pymongo import MongoClient 

db = MongoClient().test 

now = 1225 
r = db.test.find({ 
    'last_updated': {'$lte': {'$subtract': [now, '$update_interval']}} 
}) 
for item in r: 
    print(r) 

但是,它不显示任何信息。但是当我将{'$subtract': [now, '$update_interval']}更改为硬编码值1175时,它工作正常。

我认为我不能使用$subtract外聚集的管道,所以我尝试另:

r = db.test.aggregate([ 
    { 
     '$match': { 
      'last_updated': {'$lte': {'$subtract': [now, '$update_interval']}}, 
     }, 
    }, 
]) 

嗯,它只是看起来与以前的一个,并且是它没有工作过。

最后,我给了最后一次尝试:

r = db.test.aggregate([ 
    { 
     '$project': { 
      'when_to_update': {'$subtract': [now, '$update_interval']}, 
      'last_updated': True, 
      'update_interval': True, 
     }, 
    }, 
    { 
     '$match': { 
      'last_updated': {'$lte': '$when_to_update'}, 
     }, 
    }, 
]) 

好吧,它不会再工作。但奇怪的是,当我刚刚获得通过的$project管道,结果是这样的:

{'_id': ObjectId('AAA'), 'last_updated': 1000.0, 'update_interval': 50.0, 'when_to_update': 1175.0} 
{'_id': ObjectId('BBB'), 'last_updated': 1200.0, 'update_interval': 50.0, 'when_to_update': 1175.0} 

所以应该通过$match管道太后工作!我错过了什么吗?等待你的答案,谢谢。

+1

你不能比较比赛阶段的领域。这是可能的3.6版本。简单的解决方法是改变''can_update':{'$ lte':['$ last_updated', {'$ subtract':[now,'$ update_interval']}]}''和'{''''匹配':{ 'can_update':true, }, }' – Veeram

+0

[MongoDb查询条件比较2个字段]的可能重复(https://stackoverflow.com/questions/4442453/mongodb-query-condition-on-比较2字段) – Veeram

回答

1

对,你不能在汇总管道外使用$减法。聚合投影运算符对聚合框架是唯一的。

目前,在$ match表达式中使用字段值是非常棘手的;在MongoDB 3.6中,新的$ expr操作符将有所帮助。同时试试这个:

now = 1225 
r = db.test.aggregate([ 
    { 
     '$project': { 
      'comparison': {'$cmp': [ 
       now, 
       [{'$sum': ['$update_interval', '$last_updated']}]]}, 
      'last_updated': True, 
      'update_interval': True 
     } 
    }, { 
     '$match': { 
      'comparison': -1 
     } 
    } 
]) 

for item in r: 
    print(item) 

在你的for-loop中,你必须打印“item”,而不是“r”。

+0

谢谢你的一个很好的建议。顺便说一句,我已经找到了一种方法,通过'r = db.test.aggregate([{'$ addFields':{'when_to_update':{'$ add':['$ last_refreshed','$ interval']}} },{'$ match':{'when_to_update':{'$ lte':now}}}])'。而且,我想现在更新我的mongodb服务器到3.6 ... – hallazzang

+0

太棒了。 MongoDB 3.6将在几个月后出来,同时你可以下载3.5.x开发版本:https://www.mongodb.com/download-center#development –