首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >umongo,pymongo,python 3,如何从参考字段加载数据

umongo,pymongo,python 3,如何从参考字段加载数据
EN

Stack Overflow用户
提问于 2020-04-18 16:16:55
回答 1查看 584关注 0票数 0

我正在试图理解为什么在unmongo/pymongo中加载引用的数据如此困难。

代码语言:javascript
复制
@instance.register
class MyEntity(Document):
    account = fields.ReferenceField('Account', required=True)
    date = fields.DateTimeField(
        default=lambda: datetime.utcnow(),
        allow_none=False
    )
    positions = fields.ListField(fields.ReferenceField('Position'))
    targets = fields.ListField(fields.ReferenceField('Target'))

    class Meta:
        collection = db.myentity

当我检索到这个时:

代码语言:javascript
复制
    def find_all(self):
        items = self._repo.find_all(
            {
                'user_id': self._user_id
            }
        )
        return items

然后像这样抛出它:

代码语言:javascript
复制
    from bson.json_util import dumps

    all_items = []
    for item in all_items:
        all_items.append(item.dump())


    return dumps(all_items)

我得到以下JSON对象:

代码语言:javascript
复制
[
  {
    "account": "5e990db75f22b6b45d3ce814",
    "positions": [
      "5e9a594373e07613b358bdbb",
      "5e9a594373e07613b358bdbe",
      "5e9a594373e07613b358bdc1"
    ],
    "date": "2020-04-18T01:34:59.919000+00:00",
    "id": "5e9a594373e07613b358bdcb",
    "targets": [
      "5e9a594373e07613b358bdc4",
      "5e9a594373e07613b358bdc7",
      "5e9a594373e07613b358bdca"
    ]
  }
]

没有dump

代码语言:javascript
复制
<object Document models.myentity.schema.MyEntity({
'targets':
    <object umongo.data_objects.List([
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Target,
            pk=ObjectId('5e9a594373e07613b358bdc4')
            )>,
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Target,
            pk=ObjectId('5e9a594373e07613b358bdc7')
            )>,
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Target,
            pk=ObjectId('5e9a594373e07613b358bdca'))>]
            )>,
            'id': ObjectId('5e9a594373e07613b358bdcb'),
'positions':
    <object umongo.data_objects.List([
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Position,
            pk=ObjectId('5e9a594373e07613b358bdbb')
        )>,
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Position,
            pk=ObjectId('5e9a594373e07613b358bdbe'))>,
        <object umongo.frameworks.pymongo.PyMongoReference(
            document=Position,
            pk=ObjectId('5e9a594373e07613b358bdc1'))>])>,
'date': datetime.datetime(2020, 4, 18, 1, 34, 59, 919000),
'account': <object umongo.frameworks.pymongo.PyMongoReference(document=Account, pk=ObjectId('5e990db75f22b6b45d3ce814'))>
})>

  1. ,我真的很纠结于如何取消它。我希望,递归地将所有加载的字段(如果我在umongo模式中指定它们)取消引用。这不是在umongo中吗?

也就是说,如果在“目标”中也有一个参考字段,那该怎么办?我知道这在DB上是很昂贵的,但是有什么方法可以在模式定义本身上指定这一点吗?也就是说,在元类中,我总是想要一个特定字段的完整的、取消引用的对象?

  1. 发现关于这个问题的文档/评论非常少,在umongo文档中甚至没有提到它,我找到的其他ODM的一些解决方案(比如mongoengine)正在痛苦地为每个字段/每个查询编写递归的手动函数。这对我来说是有原因的,这不是一个受欢迎的问题。可能是反模式?如果是,为什么?

我对芒果并不陌生,但对巨蟒/蒙戈来说却是新的。我觉得我错过了一些最基本的东西。

编辑:所以在发帖后,我确实找到了这个问题:

https://github.com/Scille/umongo/issues/42

它提供了一个前进的方向

这仍然是最好的办法吗?还在努力弄明白为什么这件事被当作一个边缘案件来处理。

编辑2:进展

代码语言:javascript
复制
class MyEntity(Document):
    account = fields.ReferenceField('Account', required=True, dump=lambda: 'fetch_account')
    date = fields.DateTimeField(
        default=lambda: datetime.utcnow(),
        allow_none=False
    )
    #trade = fields.DictField()
    positions = fields.ListField(fields.ReferenceField('Position'))
    targets = fields.ListField(fields.ReferenceField('Target'))

    class Meta:
        collection = db.trade

    @property
    def fetch_account(self):
        return self.account.fetch()

因此,对于新定义的房地产装饰师,我可以这样做:

代码语言:javascript
复制
    items = MyEntityService().find_all()
    allItems = []
    for item in allItems:
        account = item.fetch_account
        log(account.dump())
        allItems.append(item.dump())

当我转储账户时,一切都很好。但我不想显式地/手动地这样做。这仍然意味着每次进行查询时,我都必须递归地解压缩,然后重新打包每个引用的文档和任何子引用。这还意味着模式SOT不再仅仅包含在umongo类中,也就是说,如果字段发生变化,我将不得不重构使用该字段的每个查询。

我仍然在寻找一种方式来装饰/标记模式本身。例如:

代码语言:javascript
复制
    account = fields.ReferenceField('Account', required=True, dump=lambda: 'fetch_account')

dump=lambda: 'fetch_account'我刚刚编好了,它什么也不做,但这或多或少是我想要的模式,我不确定这是否可能(甚至是聪明的:其他方向,指点为什么我的方法完全错误是值得欢迎的).

编辑3:这就是我登陆的地方:

代码语言:javascript
复制
    @property
    def fetch_account(self):
        return self.account.fetch().dump()

    @property
    def fetch_targets(self):
        targets_list = []
        for target in self.targets:
            doc = target.fetch().dump()
            targets_list.append(doc)
        return targets_list

    @property
    def fetch_positions(self):
        positions_list = []
        for position in self.positions:
            doc = position.fetch().dump()
            positions_list.append(doc)
        return positions_list

然后进入:

代码语言:javascript
复制
    allItems = []
    for item in items:
        account = item.fetch_account
        positions = item.fetch_positions
        targets = item.fetch_targets

        item = item.dump()
        item['account'] = account
        item['positions'] = positions
        item['targets'] = targets
        # del item['targets']
        allTrades.append(item)

我可以清理它/抽象它一些,但我不知道在这一点上我如何才能真正减少一般的冗长。不过,这似乎确实给了我我想要的结果:

代码语言:javascript
复制
[
  {
    "date": "2020-04-18T01:34:59.919000+00:00",
    "targets": [
      {
        "con_id": 331641614,
        "value": 106,
        "date": "2020-04-18T01:34:59.834000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdc4"
      },
      {
        "con_id": 303019419,
        "value": 0,
        "date": "2020-04-18T01:34:59.867000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdc7"
      },
      {
        "con_id": 15547841,
        "value": 9,
        "date": "2020-04-18T01:34:59.912000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdca"
      }
    ],
    "account": {
      "user_name": "hello",
      "account_type": "LIVE",
      "id": "5e990db75f22b6b45d3ce814",
      "user_id": "U3621607"
    },
    "positions": [
      {
        "con_id": 331641614,
        "value": 104,
        "date": "2020-04-18T01:34:59.728000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdbb"
      },
      {
        "con_id": 303019419,
        "value": 0,
        "date": "2020-04-18T01:34:59.764000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdbe"
      },
      {
        "con_id": 15547841,
        "value": 8,
        "date": "2020-04-18T01:34:59.797000+00:00",
        "account": "5e990db75f22b6b45d3ce814",
        "id": "5e9a594373e07613b358bdc1"
      }
    ],
    "id": "5e9a594373e07613b35
8bdcb"
  }
]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-18 18:42:44

这似乎是乌龙戈的一个设计选择。

例如,在Mongoid ( Ruby for MongoDB)中,当引用对象时,会根据需要通过关联从数据库中自动获取对象。

顺便说一下,在ODM中,“定义字段结构”和“通过应用程序对象无缝访问数据”的功能是完全独立的。例如,我在Java中使用Hibernate的经验表明,它与您在umongo中发现的类似--一旦加载了数据,它就提供了一种使用应用程序定义的具有类型等字段结构访问数据的方法,但它实际上无助于透明地从应用程序域加载数据。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61292375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档