Pymongo聚合具有多种条件:查找,展开,编辑,转换,排序和限制

时间:2018-04-03 11:31:32

标签: python mongodb aggregate pymongo lookup

done_status = ['BAD_PU', 'TO_WH', 'RCVDPORT', 'RCVD', 'BAD_DEL', 'MISSFLT', 'OFFLOAD']

shipments = db.db_shipment.aggregate([{
    "$lookup":{
        "from":"db_shipment_status_history",
        "localField":"_id",
        "foreignField":"fk_shipment_id",
        "as":"shipment_status_history_collection"
        }
    },
    {"$unwind":
        "$shipment_status_history_collection"},
        {"$redact":{"$cond":{ "$if": { "status_value": {"$in": done_status } } },
                "$then": "$$KEEP"
                ,"$else":"$$PRUNE"
                }
            },
        {"$sort":
            {'shipment_status_history_collection.rec_timestamp':-1}},
        {"$limit":1},
        {"$project":{"pkey":"$pkey","_code":"$_code"}}
    ])

错误:

  

pymongo.errors.OperationFailure:表示表达式的对象必须只有一个字段:{$ cond:{$ if:{status_value:{$ in:[“BAD_PU”,“TO_WH”,“RCVDPORT”,“RCVD “,”BAD_DEL“,”MISSFLT“,”OFFLOAD“]}}},$ else:”$$ PRUNE“,$ then:”$$ KEEP“}

如何修复此错误?我试图在货件记录中添加最新的货件状态历史记录,其中状态值处于给定的状态值。

1 个答案:

答案 0 :(得分:1)

更新聚合管道的编辑阶段。 ifthenelse$cond运算符的一部分,它们本身不是运算符。

此外,$in运算符将传递一个数组,其中第一项检查是否存在于第二项中。第二项通常是可迭代的。

Mongo 3.6

messenger_pipeline_status = (
    messenger_active_status['data']['pending'] 
    + messenger_active_status['data']['processing']
)
assigned_status = ['DEL_ASSIGNED','PU_ASSIGNED']

subpipeline =  [
    {
        '$match': {
            '$expr': {
                '$and': [
                    {'$eq': ['$fk_shipment_id', '$$pkey']},
                    {'$eq': ['$fk_messenger_id', fk_user_id]},
                    {'$in': ['$status_value', assigned_status]}
                ]
            }                       
        }
    },

    {
        '$sort': {
            'rec_timestamp': -1
        }
    },

    {
        '$limit': 1
    },

    {
        '$project': {
            'fk_shipment_id': 1
        }
    }
]

pipeline = [
    {
        '$match': {
            'status_value': {'$in': messenger_pipeline_status}
            'is_deleted': False,
            'is_postponed': False,
            'is_active': True,
        }
    },

    {
        '$lookup': {
            'from': 'db_shipment_status_history',
            'let': {'pkey':  '$pkey'},
            'pipeline': subpipeline,
            'as': 'shipment_status_history'
        }
    },

    {
        '$match': {
            'shipment_status_history': {
               '$ne': [] 
            } 
        }
    },

    {
        '$unwind': '$shipment_status_history'
    },

    {
        '$project': {
            '_id': 1,
            'pkey': 1,
            '_code': 1,
            'date_created': 1,
            'sender_full_name': '$sender.full_name',
            'sender_raw_address': '$sender.raw_address',
            'sender_formatted_address': '$sender.formatted_address',
            'receiver_full_name': '$receiver.full_name',
            'receiver_raw_address': '$receiver.raw_address',
            'receiver_formatted_address': '$receiver.formatted_address',
            'status_name': 1,
            'team_value': 1,
            'cs_name': 1,
            'fk_messenger_id': '$shipment_status_history.fk_shipment_id'
        }
    }   
]

result = db.db_shipment.aggregate(pipeline)
print(list(result))

[编辑] Mongo 3.2

以下聚合管道产生与上述类似的结果,并且是Mongo 3.2的有效查询。

messenger_pipeline_status = ['MISSFLT', 'OFFLOAD']
pipeline = [
    {
        '$match': {
            'status_value': { '$in': messenger_pipeline_status}
            'is_deleted': False,
            'is_postponed': False,
            'is_active': True,
        }
    },
    {
        "$lookup": {
            'from': 'db_shipment_status_history',
            'localField': 'pkey',
            'foreignField': 'fk_shipment_id',
            'as': 'shipment_status_history'
        }
    },

    {
        '$match': {
            'shipment_status_history': {
               '$ne': [] 
            } 
        }
    },

    {
        '$project': {
            '_id': 1,
            'pkey': 1,
            '_code': 1,
            'date_created': 1,
            'sender_full_name': '$sender.full_name',
            'sender_raw_address': '$sender.raw_address',
            'sender_formatted_address': '$sender.formatted_address',
            'receiver_full_name': '$receiver.full_name',
            'receiver_raw_address': '$receiver.raw_address',
            'receiver_formatted_address': '$receiver.formatted_address',
            'status_name': 1,
            'team_value': 1,
            'cs_name': 1,
            'shipment_status_history': {
                '$filter': {
                    'input': '$shipment_status_history',
                    'as': 'shipment',
                    'cond': {
                        '$and': [
                            {'$eq': ['$$shipment.fk_shipment_id', fk_user_id]},
                            {'$in': ['$$shipment.status_value', assigned_status]},
                        ]
                    }
                }
            },
        }
    },

    {
        '$unwind': '$shipment_status_history'
    },

    {
        '$sort': {
            'shipment_status_history.rec_timestamp': -1,
        }
    },

    {
        '$group': {
            '_id': '$pkey',
            'doc': {
                '$first': '$$CURRENT'
            }
        }
    },

    {
        '$unwind': '$doc'
    },

    { # last projection, I promise
        '$project': {
            '_id': '$doc.id',
            'pkey': '$doc.pkey',
            '_code': '$doc._code',
            'date_created': '$doc.date_created',
            'sender_full_name': '$doc.sender_full_name',
            'sender_raw_address': '$doc.sender_raw_address',
            'sender_formatted_address': '$doc.sender_formatted_address',
            'receiver_full_name': '$doc.receiver_full_name',
            'receiver_raw_address': '$doc.receiver_raw_address',
            'receiver_formatted_address': '$doc.receiver_formatted_address',
            'status_name': '$doc.status_name',
            'team_value': '$doc.team_value',
            'cs_name': '$doc.cs_name',
            'fk_messenger_id': '$doc.shipment_status_history.fk_shipment_id'
        }
    },
]

res = db.db_shipment.aggregate(pipeline)