He insertado el siguiente documento en mi base de datos mongo usando Python:

@cherrypy.expose
def create(self):
    client = MongoClient()
    db = client.database_name        
    result = db.users.insert_one({
        "email": "email@email.com",
        "company": {
            "name": "ABC Company"
        }
    })

Ahora, he almacenado los resultados de la consulta de la colección, usando variables (company_name):

 @cherrypy.expose
 def result(self):
     client = MongoClient()
     db = client.database_name        
     cursor = db.users.find({"email":"email@email.com"})
     for document in cursor:
        email = document["email"]
        company_name = document["company"]["name"]
     return company_name

Me gustaría devolver el elemento anidado como objeto, como: company.name en lugar de variable (company_name)

¿Cómo puedo modificar mi función de resultado para almacenar los resultados de la colección como atributos de objeto?

1 - Estoy usando CherryPy como servidor HTTP. No estoy usando ningún ORM ni motor de plantillas.

1
Rimo 31 dic. 2016 a las 23:08
1
Debe crear una clase de Python que describa el objeto y devolver una instancia de la clase.
 – 
DYZ
31 dic. 2016 a las 23:16
Aclare: ¿desea devolver el objeto { "email": "email@email.com", "company": { "name": "ABC Company" } } completo del controlador HTTP en formato JSON?
 – 
webknjaz
1 ene. 2017 a las 19:44
Sí, quiero devolver el objeto completo.
 – 
Rimo
2 ene. 2017 a las 15:45

1 respuesta

La mejor respuesta

Utilice namedtuple del módulo collections:

from collections import namedtuple
company = namedtuple('company ', 'name') 
document = namedtuple('document ', 'email, company')

Y luego dentro del bucle:

for row in cursor:
    result = document(row["email"], company(row["company"]["name"]))
    yield result # or 'return result' if there is only one of them

namedtuple accederá a sus argumentos (pero solo lectura ya que es una tupla) tanto como posicionales (por índice [0], [1], etc.) y como atributos (result.email). Todos los atributos también son propiedades de solo lectura, por lo que vienen con la función fget prefabricada que se puede usar en map y filter.

0
Dmitry Rubanovich 31 dic. 2016 a las 23:59
¿Puedo pasar estos como argumentos a otras funciones usando esta nueva notación? por ejemplo - def new (result.name)
 – 
Rimo
2 ene. 2017 a las 18:09
O mejor, ¿cómo debo pasarlos a un archivo? Siguiendo este ejemplo: return template.format (result = result)?
 – 
Rimo
2 ene. 2017 a las 18:21
@Gerr, cualquier instancia creada con la función de construcción que obtenga de namedtuple es, de hecho, una tupla y una instancia de clase. Entonces puedes usarlo como cualquiera. En una nota no relacionada, no usaría new como nombre para su propia función porque Python ya la usa durante el proceso de creación de objetos regulares. Puede resultar confuso en la depuración o, peor aún, estropear el proceso de creación de objetos normal. Otra cosa a tener en cuenta es que namedtuple se implementa puramente en Python (no C), por lo que puede echar un vistazo a lo que hace dentro del módulo collections.
 – 
Dmitry Rubanovich
3 ene. 2017 a las 03:42