postgresql Django|如何查询foreignkey并仅返回特定键上的一个对象(预取)

vlf7wbxs  于 12个月前  发布在  PostgreSQL
关注(0)|答案(1)|浏览(133)

我正在头痛地写一个查询:slight_smile:这是我的模型:

`class Mission(models.Model):
    machine = models.ForeignKey(Machine, on_delete=models.CASCADE, related_name="missions")
    start_dt = models.DateTimeField(null=False)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True)
    latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True)

    @cached_property
    def timezone(self) -> datetime.tzinfo:
        timezone_str = get_tz(float(self.longitude), float(self.latitude))
        return pytz.timezone(timezone_str)`

`class Machine(models.Model):
    name = models.CharField(max_length=12, null=False, unique=True)
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)`

我想对所有机器进行查询,并为每台机器创建一个last_使命字段,其中包含我的最后一个使命。
例如:
machine.last_mission.timezone ...
.我完全被django ORM卡住了。
这是我的postgres查询,它并不完全符合我的要求,因为没有last_使命键,也没有model属性。
非常感谢你的帮助:slight_smile:
select * from machines_machine machine, missions_mission mission where (mission.machine_id, mission.start_dt) in (select mission.machine_id as machine_id, Max(mission.start_dt) as start_dt from missions_mission mission group by mission.machine_id order by mission.machine_id)

xdnvmnnf

xdnvmnnf1#

你可以在一个子查询中用最新的使命注解一个json对象:

latest_mission = Subquery(
    Mission.objects.filter(
        machine_id=OuterRef("id"),
    )
    .order_by("-start_dt")
    .values(
        mission=JSONObject(
            id="id", start_dt="start_dt", longitude="longitude", latitude="latitude"
        )
    )[:1]
)

machines = Machine.objects.all().annotate(latest_mission=latest_mission)
for machine in machines:
    print(machine.name, machine.latest_mission)

它应该返回如下内容:

AX001 {'id': 2, 'start_dt': '2021-02-01 01:00:00', 'longitude': 1, 'latitude': 1}
AX002 {'id': 4, 'start_dt': '2022-02-01 01:00:00', 'longitude': 1, 'latitude': 1}

生成的SQL查询是:

SELECT "app_machine"."id", "app_machine"."name", "app_machine"."created_at", "app_machine"."updated_at", (
    SELECT JSON_OBJECT(id, U0."id", start_dt, U0."start_dt", longitude, U0."longitude", latitude, U0."latitude") AS "mission" 
    FROM "app_mission" U0 
    WHERE U0."machine_id" = ("app_machine"."id") 
    ORDER BY U0."start_dt" DESC LIMIT 1) AS "latest_mission"
FROM "app_machine"

相关问题