Django - 为每个外键 ID 获取一个时间戳 (MySQL)

Django - Get a single timestamp per foreign key ID (MySQL)

我无法在以下模型中为每个外键 ID 仅获取一条记录,我已经尝试过此查询,但它目前似乎根本没有做任何事情

我使用了一个有效的 RAW 查询,但我不能对其使用过滤器。我还创建了一个列表并从 QuerySet 中删除了重复项,但我还是无法过滤它,因为它是一个列表

查询:

queryset = BGPData.objects.annotate(max_timestamp=Max('timestamp')).filter(timestamp=F('max_timestamp')).select_related(
    'device_circuit_subnet__subnet',
    'device_circuit_subnet__device',
    'device_circuit_subnet__circuit',
    'device_circuit_subnet__device__site',
    )

型号:

class BGPData(models.Model):
    device_circuit_subnet = models.ForeignKey(DeviceCircuitSubnets, verbose_name="Device", on_delete=models.CASCADE)
    bgp_peer_as = models.CharField(max_length=20, verbose_name='BGP Peer AS', blank=True, null=True)
    bgp_session = models.CharField(max_length=10, verbose_name='BGP Session', blank=True, null=True)
    bgp_routes = models.CharField(max_length=10, verbose_name='BGP Routes Received', blank=True, null=True)
    service_status = models.CharField(max_length=10, verbose_name='Service Status', blank=True, null=True)  
    timestamp = models.DateTimeField(auto_now=True, blank=True, null=True)  

我正在测试的示例数据(打印为字典),"device_circuit_subnet_id" 应该只有一个记录:“10”,最新的一个。

我想要每个 device_circuit_subnet_id 的最新记录,因此查询应该 return 3 个结果而不是 4 个,因为有 2 个项目具有相同的 device_circuit_subnet_id.

我读过 distinct 用于此目的,但 运行 MySQL,还有其他方法吗?

谢谢

[{
        "id": 4,
        "device_circuit_subnet_id" : "10",
        "hostname": "EDGE",
        "circuit_name": "MPLS",
        "subnet": "172.1.1.1",
        "subnet_mask": "/30",
        "bgp_session": "1w2d",
        "bgp_routes": "377",
        "bgp_peer_as": "1",
        "service_status": "Up",
        "timestamp": "2019-11-18 16:16:17"
    },
    {
        "id": 5,
        "device_circuit_subnet_id" : "11",
        "hostname": "INT-GW",
        "subnet": "1.1.1.1",
        "subnet_mask": "/24",
        "bgp_session": null,
        "bgp_routes": null,
        "bgp_peer_as": null,
        "service_status": "unknown",
        "timestamp": "2019-08-07 14:46:00"
    },
    {
        "id": 8,
        "hostname": "EDGE",
        "device_circuit_subnet_id" : "20",
        "circuit_name": "MPLS 02",
        "subnet": "172.2.1.1",
        "subnet_mask": "/30",
        "bgp_session": null,
        "bgp_routes": null,
        "bgp_peer_as": null,
        "service_status": "unknown",
        "timestamp": "2019-11-15 16:18:30"
    },
    {
        "id": 9,
        "hostname": "EDGE",
        "device_circuit_subnet_id" : "10",
        "circuit_name": "MPLS",
        "subnet": "172.1.1.1",
        "subnet_mask": "/30",
        "bgp_session": "1w3d",
        "bgp_routes": "385",
        "bgp_peer_as": "1",
        "service_status": "Up",
        "timestamp": "2019-11-18 16:16:44"
    }
]

谢谢

Django 查询集以惰性方式求值。因此,此查询只会从数据库中获取一条记录。由于有-前缀,时间戳的顺序是降序的,所以最新的时间戳值将是第一条记录。

queryset = BGPData.objects.all().order_by(
    #prefix field name to order by with `-` to use Descending order
    '-timestamp'
).select_related(
    'device_circuit_subnet__subnet',
    'device_circuit_subnet__device',
    'device_circuit_subnet__circuit',
    'device_circuit_subnet__device__site',
)[0]

你试过吗?


<b>from django.db.models import Max, F</b>

<b>max_timestamp = Max('device_circuit_subnet__bgpdata__timestamp')</b>
result = BGPData.objects.annotate(<b>ts=max_timestamp</b>).filter(<b>timestamp=F('ts')</b>).select_related(...)

我不确定此查询的性能,但它会起作用:) :)