本文介绍了如何在mongoengine中获取ReferenceField数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在查询集中检索json中的oid时遇到问题,我想检索我在下面具有的该用户集合的实际用户名:

I'm have a problem that query set retrieving oid in json, and I would like to retrieve actual username of that User collection I have below:

class User(db.Document):
    username      = db.StringField(required=True)
    password_hash = db.StringField()
    is_admin      = db.IntField(default=0)

class Message(db.EmbeddedDocument):
    to_users     = db.ListField(db.ReferenceField(User))
    created_at   = db.DateTimeField(default=datetime.now)
    is_read      = db.BooleanField(default=False)
    body         = db.StringField(required=True)

class Inbox(db.Document):
    from_user    = db.ReferenceField(User, required=True)
    subject      = db.StringField(max_length=255, required=True)
    created_at   = db.DateTimeField(default=datetime.now)
    messages     = db.ListField(db.EmbeddedDocumentField(Message))

username = User().get_username()
username = User.objects(username=username).first()

inbox = Inbox.objects.filter(messages__to_users__in=[username]).only('from_user', 'subject', 'created_at').to_json()

这就是我得到的结果:

[{"created_at": {"$date": 1401593024844}, "from_user": {"$oid": "538ad45fb43fdd69076d3e64"}, "subject": "test"}]

有这样的东西会很高兴:

Would be nice to have something like this:

[{"created_at": {"$date": 1401593024844}, "from_user": {"username": "holms"}, "subject": "test"}]

或类似"from_user" : {"User": {"username":"holms"}}

更新

以上答案适用于Document中的ReferenceField,但是EmbeddedDocument引用又如何呢?假设我要在only()中添加消息"?

Above answer works for the ReferenceField that is in Document, but what about EmbeddedDocument references? Let's say I'll add "messages" to only()?

In [97]: inbox = Inbox.objects(messages__to_users__in=[username]).only('from_user', 'subject', 'created_at', 'messages').select_related()

目前,我已经找到了映射字典的方法,这很痛苦.

Currently I've found the way by mapping dictionary which is quite painful.

In [125]: for entry in inbox:
    item = dict(subject=entry.subject, messages=map(lambda msg: dict(body=msg.body, is_read=msg.is_read, to_users=map(lambda usr: usr.username, msg.to_users)), entry.messages), from_user=entry.from_user.username)
    result.append(item)
   .....:

In [126]: result
Out[126]:
[
 {'from_user': u'holms',
  'messages': [{'body': u'test body',
    'is_read': False,
    'to_users': [u'holms']}],
  'subject': u'test'}]

更新2 似乎可以解决问题

 57     def to_json(self):
 58         data = self.to_mongo() # get pymongo representation
 59         data["from_user"] = {"User": {"username": self.from_user.username} }
 60
 61         for key, reply in enumerate(data["messages"]):
 62             for user in self.messages[key].to_users:
 63                 print user.username
 64             reply["to_users"] = {"User": {"username": user.username} }
 65
 66         return json_util.dumps(data)

您会得到:)

    {
       "_id":{
          "$oid":"538ad500b43fdd690e2eefb5"
       },
       "from_user":{
          "User":{
             "username":"holms"
          }
       },
       "subject":"test",
       "created_at":{
          "$date":1401593024844
       },
       "messages":[
          {
             "to_users":{
                "User":{
                   "username":"holms"
                }
             },
             "created_at":{
                "$date":1401593024845
             },
             "is_read":false,
             "body":"test body"
          }
       ]

    }

推荐答案

当前不直接支持此功能,因为MongoEngine仅支持mongodb的扩展json语法.

Currently this is not supported directly as MongoEngine only supports mongodb's extended json syntax.

所有mongoengine在后台进行的操作都是使用pymongo的json_utils转储数据.没有理由不能明确使用它,例如:

All mongoengine does under the covers is use pymongo's json_utils to dump the data. Theres no reason why you can't use it explicitly eg:

    from bson import json_util

    class Inbox(db.Document):
        from_user    = db.ReferenceField(User, required=True)
        subject      = db.StringField(max_length=255, required=True)
        created_at   = db.DateTimeField(default=datetime.now)
        messages     = db.ListField(db.EmbeddedDocumentField(Message))


        def to_json(self):
            data = self.to_mongo() // get the pymongo representation of the document
            data["from_user"] = {"User": {"username": self.from_user.username}}
            return json_util.dumps(data)

            User.drop_collection()

    ...

    Inbox.drop_collection()

    ross = User(username="Ross").save()
    Inbox(from_user=ross, subject="Mongoengine should make json easier").save()

    doc = Inbox.objects.only('from_user', 'subject', 'created_at').get()
    print doc.to_json()

    {"_id": {"$oid": "538c3d71c3d384172fe35393"}, 
     "from_user": {"User": {"username": "Ross"}}, 
     "subject": "Mongoengine should make json easier", 
     "created_at": {"$date": 1401703297198}, "messages": []}

已更新

带有自定义查询集的示例:

Updated

Example with custom queryset:

   from bson import json_util

    class CustomQuerySet(QuerySet):
         def to_json(self):
            return "[%s]" % (",".join([doc.to_json() for doc in self]))

    class Inbox(Document):
        from_user    = ReferenceField(User, required=True)
        subject      = StringField(max_length=255, required=True)
        created_at   = DateTimeField(default=datetime.now)
        messages     = ListField(EmbeddedDocumentField(Message))

        meta = {'queryset_class': CustomQuerySet}

        def to_json(self):
            data = self.to_mongo()
            data["from_user"] = {"User": {"username": self.from_user.username}}
            return json_util.dumps(data)

  ...
  ipdb> Inbox.objects.only('from_user', 'subject', 'created_at').to_json()
        '[{"_id": {"$oid": "538d84cbc3d3843eeeb5dbbe"}, 
           "from_user": {"User": {"username": "Ross"}}, 
           "subject": "Mongoengine should make json easier", 
           "created_at": {"$date": 1401787099246}, "messages": []}]'

这篇关于如何在mongoengine中获取ReferenceField数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 09:02