Mongoengine聚合查询与Mongo相比有所不同

4

我有一个Mongo文档,里面包含嵌套的文档列表(如下所示)。我正在尝试运行聚合操作,以仅返回列表中匹配的对象并搭配完整文档。

示例集合数据

{
    "make": "Toyota",
    "color": "blue",
    "tires": [{
        "make": "Mishlen",
        "size": 185
    }, {
        "make": "Mishlen",
        "size": 210
    }]
}

我使用以下查询成功在MongoDB中实现了它:

db.cars.aggregate(
    [
        {
            $match: {$and: [{"tires.size": {$gt: 200}}]}
        },
        {
            $addFields: {
                "tires": {
                    $filter: {
                        input: '$tires',
                        as: 'tires',
                        cond: {$gt: ['$$tires.size', 200]}
                    }
                }
            }
        },
        {
            $limit: 100
        },
        {
            $skip: 0
        }
])

我正在尝试在mongoengine中运行相同的聚合操作,但每次都返回一个空列表。
pipeline = [
    {
        "$match": {"$and": [{"tires.size": {"$gt": 200}}]}
    },
    {
        "$addFields": {
            "tires": {
                "$filter": {
                    "input": "$tires",
                    "as": "tires",
                    "cond": {"$and": [{"$gt": ["$$tires.size", 200]}]}
                }
            }
        }
    }
]
self.obj_type.objects.aggregate(*pipeline)

我做错了什么?

更新

我的问题比我想象中简单,我在Python中传递的是字符串而不是整数。感谢大家的帮助。

2个回答

2

在插入您提供的示例文档后,我使用您提供的管道运行聚合时没有任何特殊问题。请参见以下内容:

class Tire(EmbeddedDocument):
    make = StringField()
    size = IntField()

class Car(Document):
    make = StringField()
    color = StringField()
    tires = EmbeddedDocumentListField(Tire)

    meta = {'collection': 'cars'}

pipeline = [
    {
        "$match": {"$and": [{"tires.size": {"$gt": 200}}]}
    },
    {
        "$addFields": {
            "tires": {
                "$filter": {
                    "input": "$tires",
                    "as": "tires",
                    "cond": {"$and": [{"$gt": ["$$tires.size", 200]}]}
                }
            }
        }
    }
]

# Verify aggregation pipeline runs fine with the driver (pymongo)
coll = Car._get_collection()
pymongo_result = list(coll.aggregate(pipeline))
assert len(pymongo_result) == 1

# Run same aggregation pipeline with MongoEngine
mongoengine_result = list(Car.objects.aggregate(*pipeline))
assert len(mongoengine_result) == 1

result = [
    {'_id': ObjectId('5e0a5c8e7c57cd9b300710fb'),
     'color': 'blue',
     'make': 'Toyota',
     'tires': [{'make': 'Mishlen', 'size': 210.0}]
    }
]
assert mongoengine_result == pymongo_result == result

我使用了最新的MongoEngine版本,但据我所知,最近MongoEngine的聚合包装器没有发生重大变化。可能问题出现在你的self.obj_type.objects上,请尝试像我一样从一个新的查询集开始(即YourDocumentClass.objects),看看是否有所不同。


1
以下工作流程将是最简单的。
 pipeline = [
            {
        $unwind: "$tires"
            },
            {
                "$match": {"$and": [{"tires.size": {"$gt": 200}}]}
            },
            {
         $group : { 
                   _id : "$make", 
                   tires: { $push: "$tires" } 
                  }
            } 

        ]
        self.obj_type.objects.aggregate(*pipeline) 

它并不完全符合我需要的查询,因为它将按制造商进行分组,并且不会返回文档中的所有其他字段。另外,由于我们执行了展开和分组操作,所以效率会大大降低,因为我们将无法使用索引,并且它将在更多的文档上运行。有没有关于如何使原始查询正常工作的建议? - Michael Royf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接