【问题标题】:Pymongo - Weird aggregation behaviorPymongo - 奇怪的聚合行为
【发布时间】:2017-10-09 23:08:30
【问题描述】:

这里我在test.test 集合中有两个文档:

> 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 管道后工作!我错过了什么吗?等待您的答复,谢谢。

【问题讨论】:

  • 您无法在匹配阶段比较字段。从 3.6 版本开始可以。简单的解决方法是更改​​ 'can_update': {'$lte': ['$last_updated', {'$subtract': [now, '$update_interval']}]} 和 { '$match': { 'can_update': true, }, }

标签: python mongodb aggregation-framework pymongo


【解决方案1】:

是的,您不能在聚合管道之外使用 $subtract。聚合投影算子是聚合框架独有的。

目前,在 $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 循环中,你必须打印“item”,而不是“r”。

【讨论】:

  • 感谢您的好建议。顺便说一句,我自己通过r = db.test.aggregate([{'$addFields': {'when_to_update': {'$add': ['$last_refreshed', '$interval']}}}, {'$match': {'when_to_update': {'$lte': now}}}]) 找到了一种方法。而且,我现在想将我的 mongodb 服务器更新到 3.6...
  • 太棒了。 MongoDB 3.6 将在几个月后发布,同时您可以下载 3.5.x 开发版本:mongodb.com/download-center#development
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-15
  • 2015-06-26
  • 2019-12-22
  • 2017-08-29
  • 1970-01-01
  • 2020-01-15
相关资源
最近更新 更多