在pymodm中按对象查询相关集合?

Querying related collection by object in pymodm?

我在我的项目中使用 pymodm 作为 ORM。

我有以下简单案例:

class IdentityRecord(MongoModel):
    alias = fields.CharField()  # normal name for identity


class IdentityImage(MongoModel):
    filename = fields.CharField()  # filename on filesystem
    source_identity = fields.ReferenceField(IdentityRecord)  # reference to an identity

我们可以看到,每个IdentityImage指的是IdentityRecord

如果我有对象 IdentityRecord,那么如何在 python 代码中找到 IdentityImage 中引用该对象的所有记录?

当然,我可以这样做:

IdentityImage.objects.raw({'source_identity': identity.pk})

然而,用户 'source_identity' 字符串文字的必要性有点违背了 ORM 的目的。在此框架中是否有任何方法可以通过某种方式使用 IdentityRecord 对象的实例来查询 IdentityImage 集合?

pymodm.manager.Manager 中的选择性查询(例如问题示例中的 IdentityImage.objects)似乎需要 dict 作为 getraw 方法。相反,sqlalchemy query 中的 filter_by 方法接受关键字参数。

如果您更喜欢关键字参数而不是字符串文字,则以下表达式似乎可行。

IdentityImage.objects.raw(dict(source_identity=identity.pk))

省略该表达式中的 dict 包装表明 raw 方法不接受字段名称作为关键字参数。如果修改 pymodm 以允许这样做,则此类查询的表示法会更简单。

以下代码是问题原始代码的变体。第一 import 行在原始代码中是隐含的,在这里是显式的。另外两个 import 行启用新 class、KWQuerySet 的定义和使用。除了新 class、args 的辅助函数外,唯一的其他变化是最后一行,原始代码中 class 之一的新属性,它使用新 class。

from pymodm import MongoModel, fields
from pymodm.queryset import QuerySet
from pymodm.manager import Manager

def args(arg=None, **kwargs):
    return {**arg, **kwargs} if arg else kwargs

class KWQuerySet(QuerySet):
    def raw(self, raw_query=None, **kwargs):
        return super().raw(args(raw_query, **kwargs))
    def get(self, raw_query=None, **kwargs):
        return super().get(args(raw_query, **kwargs))

class IdentityRecord(MongoModel):
        alias = fields.CharField()  # normal name for identity                                                                                                                                                                                                                                                                                                          

class IdentityImage(MongoModel):
    filename = fields.CharField()  # filename on filesystem                                                                                                                                                                                                                                                                                                             
    source_identity = fields.ReferenceField(IdentityRecord)  # reference to an identity                                                                                                                                                                                                                                                                                 
    objects = Manager.from_queryset(KWQuerySet)()

根据突变代码中 IdentityImage 的定义,以下查询似乎在 python 3.5.3 中正常工作,与 identity 的含义相同( IdentityRecord) 隐含在问题的示例查询中。

IdentityImage.objects.raw(source_identity=identity.pk)

3.5 之前的 python 版本可能需要在变异代码中替代实现 args 函数。我还没有完全探讨这种更改对查询表示法的影响,但我相信任何将 raw_query 作为 dict 传递的查询都应该仍然有效,无论是否使用关键字参数的表示法,或者两种表示法的组合,raw_query 的字典和其他字段名称的单独关键字参数。