如何在数组中返回嵌套文档

时间:2019-05-21 04:59:34

标签: python mongodb mongodb-query aggregation-framework

我的文档具有如下架构:

{
    "user_id": 123,
    "services":[
         {"name": "test",
          "data": ...
         },
         {"name": "test1",
          "data": ...
         },
         {"name": "test2",
          "data": ...
         }
    ]
}

我正在尝试通过名称获取特定用户ID的服务,该用户ID返回如下:

{"name": "test2",
    "data": ...
}

我很难全神贯注于如何执行此操作,并且似乎不需要像这样简单的操作进行汇总,但是也许我错了。我确定投影可以在find_one语句中使用,但不确定使用什么。我正在使用Motor不确定是否有帮助。


我尝试过:

async def get_service_by_name(user_id, name):
    return await db.guilds.find_one({
        'user_id': 123,
        'services': {'$elemMatch': {'name': "test"}}},
        {'user_id: 0, 'services.$': 1}))

但这返回:

{"services":[{"name" : "test", "data" : "blah" }]}

那很好,因为它接近我想要的,而我要做的就是:

service = await get_service_by_name(123, "test")
service = service['service'][0]

但是有没有办法在没有聚合的情况下像服务一样取回数据呢?如果没有,那么聚合应该是什么样子?

修改

我想出了一个可以做到这一点的聚合方法,但是想确保没有更好的方法:

await db.guilds.aggregate([
    {'$unwind': '$services'},
    {'$match':{
        '_id': 123,
        'services.name': "test"}},
    {'$project': {
        '_id': 0,
        'name': '$services.name',
        'data': '$services.data'}}
])

1 个答案:

答案 0 :(得分:3)

您需要运行$unwindservices获取单个文档,然后运行$replaceRoot将其提升到根级别:

db.guilds.aggregate([
    {
        $match: { user_id: 123, "services.name": "test" }
    },
    {
        $unwind: "$services"
    },
    {
        $match: { "services.name": "test" }
    },
    {
        $replaceRoot: { newRoot: "$services" }
    }
])