pymongo - 获取深度嵌套的 objectID

pymongo - getting deeply nested objectID

我有一个像这样的集合:

db.attributes.find({"name" : {"en-UK" : "Fabric"}}).pretty();
{
    "_id" : ObjectId("5550dab4a14c9766418ff2dc"),
    "values" : {
        "source" : [
            {
                "code" : 1,
                "_id" : ObjectId("5550dab4a14c9766418ff2bf"),
                "name" : {
                    "fr-FR" : "Coton",
                    "it-IT" : "Cotone",
                    "en-UK" : "Cotton",
                    "es-ES" : "Algodón"
                }
            },
            {
                "code" : 2,
                "_id" : ObjectId("5550dab4a14c9766418ff2c0"),
                "name" : {
                    "fr-FR" : "Viscose",
                    "it-IT" : "Viscosa",
                    "en-UK" : "Viscose",
                    "es-ES" : "Viscosa"
                }
            },
            {
                "code" : 3,
                "_id" : ObjectId("5550dab4a14c9766418ff2c1"),
                "name" : {
                    "fr-FR" : "Coton peigné",
                    "it-IT" : "Cotone pettinato",
                    "en-UK" : "Combed Cotton",
                    "es-ES" : "Algodón peinado"
                }
            },
            {
                "code" : 4,
                "_id" : ObjectId("5550dab4a14c9766418ff2c2"),
                "name" : {
                    "fr-FR" : "Polyester",
                    "it-IT" : "Poliestere",
                    "en-UK" : "Polyester",
                    "es-ES" : "Poliéster"
                }
            },
            {
                "code" : 5,
                "_id" : ObjectId("5550dab4a14c9766418ff2c3"),
                "name" : {
                    "fr-FR" : "Tencel© Lyocell",
                    "it-IT" : "Tencel© Lyocell",
                    "en-UK" : "Tencel© Lyocell",
                    "es-ES" : "Tencel© Lyocell"
                }
            },
            {
                "code" : 6,
                "_id" : ObjectId("5550dab4a14c9766418ff2c4"),
                "name" : {
                    "fr-FR" : "Coton peigné biologique",
                    "it-IT" : "Cotone pettinato biologico",
                    "en-UK" : "Combed Organic Cotton",
                    "es-ES" : "Algodón peinado orgánico"
                }
            },
            {
                "code" : 7,
                "_id" : ObjectId("5550dab4a14c9766418ff2c5"),
                "name" : {
                    "fr-FR" : "Viscose de bambou",
                    "it-IT" : "Viscosa di bamboo",
                    "en-UK" : "Bamboo Viscose",
                    "es-ES" : "Viscosa de bambú"
                }
            },
            {
                "code" : 8,
                "_id" : ObjectId("5550dab4a14c9766418ff2c6"),
                "name" : {
                    "fr-FR" : "Coton biologique",
                    "it-IT" : "Cotone biologico",
                    "en-UK" : "Organic Cotton",
                    "es-ES" : "Algodón orgánico"
                }
            },
            {
                "code" : 9,
                "_id" : ObjectId("5550dab4a14c9766418ff2c7"),
                "name" : {
                    "fr-FR" : "Polyester recyclé",
                    "it-IT" : "Poliestere riciclato",
                    "en-UK" : "Recycled Polyester",
                    "es-ES" : "Poliéster reciclado"
                }
            },
            {
                "code" : 10,
                "_id" : ObjectId("5550dab4a14c9766418ff2c8"),
                "name" : {
                    "fr-FR" : "Modal",
                    "it-IT" : "Modal",
                    "en-UK" : "Modal",
                    "es-ES" : "Modal"
                }
            },
            {
                "code" : 11,
                "_id" : ObjectId("5550dab4a14c9766418ff2c9"),
                "name" : {
                    "fr-FR" : "Lycra Elastane",
                    "it-IT" : "Lycra élasthanne",
                    "en-UK" : "Lycra Elastane",
                    "es-ES" : "Licra Elastano"
                }
            },
            {
                "code" : 12,
                "_id" : ObjectId("5550dab4a14c9766418ff2ca"),
                "name" : {
                    "fr-FR" : "Coton issu de culture biologique, recyclé pré-consommation",
                    "it-IT" : "Cotone coltivato biologicamente riciclato pre-consumo",
                    "en-UK" : "Recycled pre-consumer cotton organically grown",
                    "es-ES" : "Algodón orgánico reciclado pre-consumo"
                }
            },
            {
                "code" : 13,
                "_id" : ObjectId("5550dab4a14c9766418ff2cb"),
                "name" : {
                    "fr-FR" : "Polyester recyclé post-consommation",
                    "it-IT" : "Poliestere riciclato post-consumo",
                    "en-UK" : "Recycled post-consumer polyester",
                    "es-ES" : "Polyéster recilado post-consumo"
                }
            },
            {
                "code" : 14,
                "_id" : ObjectId("5550dab4a14c9766418ff2cc"),
                "name" : {
                    "fr-FR" : "Élasthanne",
                    "it-IT" : "Elasthan",
                    "en-UK" : "Elastane",
                    "es-ES" : "Elastano"
                }
            }
        ],
        "name" : [
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2cd"),
                "name" : {
                    "en-UK" : "3-ply Loopback"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2ce"),
                "name" : {
                    "en-UK" : "Brushed 2-ply"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2cf"),
                "name" : {
                    "en-UK" : "Brushed 3-ply"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d0"),
                "name" : {
                    "en-UK" : "Canvas Weave"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d1"),
                "name" : {
                    "en-UK" : "Fine Jersey"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d2"),
                "name" : {
                    "en-UK" : "Fleece"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d3"),
                "name" : {
                    "en-UK" : "Interlock"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d4"),
                "name" : {
                    "en-UK" : "Jersey"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d5"),
                "name" : {
                    "en-UK" : "Piqué"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d6"),
                "name" : {
                    "en-UK" : "Plain weave"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d7"),
                "name" : {
                    "en-UK" : "Rib"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d8"),
                "name" : {
                    "en-UK" : "Sheer Jersey"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2d9"),
                "name" : {
                    "en-UK" : "Supersoft Jersey"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2da"),
                "name" : {
                    "en-UK" : "Twill weave"
                }
            },
            {
                "_id" : ObjectId("5550dab4a14c9766418ff2db"),
                "name" : {
                    "en-UK" : "Woven Twill"
                }
            }
        ]
    },
    "name" : {
        "en-UK" : "Fabric"
    }
}

我正在使用此代码获取 fabric.name

def get_attribute_fabric(name):
    attribute_fabric_meta = db.attributes.aggregate([{ '$match': {'name.en-UK': 'Fabric'} },
        { '$unwind' : '$values' },
        { '$project': { 'name' : '$values.name', 'valueId': '$values._id'} },
        { '$match': {
            '$and': [
                {'name.en-UK': str(name)}
            ]
        }
    }])

但是我得到这个错误

pymongo.errors.OperationFailure: command SON([('aggregate', u'attributes'), ('pipeline', [{'$match': {'name.en-UK': 'Fabric'}}, {'$unwind': '$values'}, {'$project': {'valueId': '$values._id', 'name': '$values.name'}}, {'$match': {'$and': [{'name.en-UK': 'Jersey'}]}}])]) failed: exception: $unwind: value at end of field path must be an array

我喜欢 return objectId

非常感谢任何建议

您不能在 'values' 上展开,因为它不是数组。您必须在 'values.source' 上放松而不是试试这个聚合管道,

[
  { '$match': {'name.en-UK': 'Fabric'} },
  { '$unwind' : '$values.source' },
  { '$project': { 'name' : '$values.source.name', 'valueId': '$values.source._id'} },
  { '$match': {'name.en-UK': str(name)}}
]

另外我认为 $and 不是必需的。保持简单,伙计:)

如果您使用的是 MongoDB 3.2 或更新版本,您可以使用 $filter 运算符来有效地做到这一点:

def get_attribute_fabric(name):
    pipeline = [{'$match': {'name.en-UK': 'Fabric'}}, 
        {'$project': {'name': {'$filter': {'input': '$values.name', 'as': 'n', 'cond': {'$eq': ['$$n.name.en-UK',  name]}}}}}
    ]
    return db.attributes.aggregate(pipeline)

演示:

>>> from pprint import pprint
>>> pprint(list(get_attribute_fabric('Woven Twill')))
[{'_id': ObjectId('5550dab4a14c9766418ff2dc'),
  'name': [{'_id': ObjectId('5550dab4a14c9766418ff2db'),
            'name': {'en-UK': 'Woven Twill'}}]}]
>>>