Peewee ORM - 过滤具有多对多关系的结果
Peewee ORM - Filtering Result with Many-To-Many Relation
全部,
我正在尝试使用 Peewee 查询用户和地址系统。我试图过滤掉多对多关系。我取回了正确的对象,但是当我通过列表(查询)return 对象时,我没有删除不匹配的关系。例如,如果我想获取纽约 (NY) 状态为 4 的用户的所有地址,我将执行这样的查询:
设置:
class Address(Model):
address_line_1 = CharField(null=True)
address_line_2 = CharField(null=True)
city = CharField(null=True)
state_abbr = CharField(null=True, max_length=2)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class LicenseNumber(Model):
number = CharField(unique=True, index=True)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class User(Model):
license = ForeignKeyField(LicenseNumber, null=True)
addresses = ManyToManyField(Address, related_name="users")
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
示例:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.having( # Also tried to ensure that I only get what we want
(Address.state == 4) &
(Address.state_abbr << ['NY'])))
# Return the users
return list(query)
当我查看对象视图 query.dict() 时,我可以查看 returned 的项目,它们是正确的。有没有办法 return 具有被过滤的关联关系的实例化用户对象?查看过滤后的记录时,我希望在执行查询时看到过滤掉的关系。
预期结果:
用户 1:
地址 1
- 状态:4
- 缩写:纽约
实际结果:
用户 1:
地址 1
- 状态:4
- 缩写:纽约
地址 2:
- 状态:2
- 缩写:纽约
目标是使用用户对象并引用通过以下方式过滤的地址:
# Return the users & their filtered information
return list(query)
在迭代记录实例时,我是否遗漏了一些东西来过滤掉关系中的记录?任何帮助都会很棒
通过仔细搜索和阅读文档,我花了一段时间才弄明白。
解决方案是使用 PeeWee 提供的 aggregate_rows 功能。此功能有助于防止 N+1 查询(您需要在其中获取相关记录)。
本质上,这将 select SELECT 语句中定义的关系。因为我们在寻找地址的状态时正在建立多对多关系,所以我们需要涉及三个 table。在这种情况下,它将是 Users、UserAddresses(通过 table)和 Addresses,它们都在 select 语句中。在查询结束时,我们需要调用 aggregate_rows() 来执行提取和组合。
代码应如下所示:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, UserAddresses, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.aggregate_rows())
# Return the users
return list(query)
我们现在收到状态的预期结果:4
全部,
我正在尝试使用 Peewee 查询用户和地址系统。我试图过滤掉多对多关系。我取回了正确的对象,但是当我通过列表(查询)return 对象时,我没有删除不匹配的关系。例如,如果我想获取纽约 (NY) 状态为 4 的用户的所有地址,我将执行这样的查询:
设置:
class Address(Model):
address_line_1 = CharField(null=True)
address_line_2 = CharField(null=True)
city = CharField(null=True)
state_abbr = CharField(null=True, max_length=2)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class LicenseNumber(Model):
number = CharField(unique=True, index=True)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class User(Model):
license = ForeignKeyField(LicenseNumber, null=True)
addresses = ManyToManyField(Address, related_name="users")
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
示例:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.having( # Also tried to ensure that I only get what we want
(Address.state == 4) &
(Address.state_abbr << ['NY'])))
# Return the users
return list(query)
当我查看对象视图 query.dict() 时,我可以查看 returned 的项目,它们是正确的。有没有办法 return 具有被过滤的关联关系的实例化用户对象?查看过滤后的记录时,我希望在执行查询时看到过滤掉的关系。
预期结果:
用户 1:
地址 1
- 状态:4
- 缩写:纽约
实际结果:
用户 1:
地址 1
- 状态:4
- 缩写:纽约
地址 2:
- 状态:2
- 缩写:纽约
目标是使用用户对象并引用通过以下方式过滤的地址:
# Return the users & their filtered information
return list(query)
在迭代记录实例时,我是否遗漏了一些东西来过滤掉关系中的记录?任何帮助都会很棒
通过仔细搜索和阅读文档,我花了一段时间才弄明白。
解决方案是使用 PeeWee 提供的 aggregate_rows 功能。此功能有助于防止 N+1 查询(您需要在其中获取相关记录)。
本质上,这将 select SELECT 语句中定义的关系。因为我们在寻找地址的状态时正在建立多对多关系,所以我们需要涉及三个 table。在这种情况下,它将是 Users、UserAddresses(通过 table)和 Addresses,它们都在 select 语句中。在查询结束时,我们需要调用 aggregate_rows() 来执行提取和组合。
代码应如下所示:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, UserAddresses, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.aggregate_rows())
# Return the users
return list(query)
我们现在收到状态的预期结果:4