如何进行可以找到 "latest" 或 "min" 或 "max" 的 graphql 查询
How to make graphql query that can find "latest" or "min" or "max"
我正在尝试将 graphql 与 python 结合使用来检索某个时间范围内的最低和最高温度。
温度 table 有 2 列:时间戳和值。
我的models.py是:
from django.db import models
class Temperature(models.Model):
timestamp = models.DateTimeField(auto_now=True)
value = models.FloatField()
def __str__(self):
return f"the value:time is {self.value}:{self.timestamp}"
和schema.py是:
class Query(graphene.ObjectType):
temperature_statistics = graphene.Field(Temperature)
def resolve_temperature_statistics(self, info, **kwargs):
before = kwargs.get("before")
after = kwargs.get("after")
return models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before)
查询 return 一个时间跨度内的最低和最高温度,应该是这样的:
query {
temperatureStatistics(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00") {
min
max
}
}
我不知道如何实现它的最小和最大部分。
因为在 graphql 查询中使用了最小值和最大值,我不能只从解析器中 return 最小值和最大值,例如,如果查询是这样写的,
query {
temperatureMax(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00")
}
我必须想办法让 graphql 完成这项工作。
回应@Ahtisham 的评论。这是我如何在没有类型的情况下实现 currentTemperature。
schema.py
import graphene
from graphene_django import DjangoObjectType
from temperature import models
class Temperature(DjangoObjectType):
class Meta:
model = models.Temperature
class Query(graphene.ObjectType):
current_temperature = graphene.Field(Temperature)
def resolve_current_temperature(self, info, **kwargs):
return models.Temperature.objects.last()
schema = graphene.Schema(query=Query)
models.py
from django.db import models
class Temperature(models.Model):
timestamp = models.DateTimeField(auto_now=True)
value = models.FloatField()
这在使用此 graphql 查询查询时有效:
query {
currentTemperature {
timestamp
value
}
}
更新 2
我已经根据@Ahtisham 的回答更新了我的 schema.py,现在将其作为我的 schema.py:
import graphene
from graphene_django import DjangoObjectType
from django.db.models import Max, Min
from temperature import models
class Temperature(DjangoObjectType):
class Meta:
model = models.Temperature
class RangeType(graphene.ObjectType):
min = graphene.String()
max = graphene.String()
class Query(graphene.ObjectType):
current_temperature = graphene.Field(Temperature, id=graphene.Int())
temperature_statistics = graphene.Field(Temperature, before=graphene.String(), after=graphene.String())
def resolve_current_temperature(self, info, **kwargs):
return models.Temperature.objects.latest('timestamp')
def resolve_temperature_statistics(self, info, before=None, after=None):
range_type = RangeType()
if before and after is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before).aggregate(Max('temperature'))
return range_type
elif before is None and after is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__gte=after).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__gte=after).aggregate(Max('temperature'))
return range_type
elif after is None and before is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__lte=before).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__lte=before).aggregate(Max('temperature'))
return range_type
else:
range_type.min_ = models.Temperature.objects.aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.aggregate(Max('temperature'))
return range_type
schema = graphene.Schema(query=Query)
Graphql 给我这个错误
{
"errors": [
{
"message": "Cannot query field \"min_\" on type \"Temperature\".",
"locations": [
{
"line": 3,
"column": 7
}
]
},
{
"message": "Cannot query field \"max_\" on type \"Temperature\".",
"locations": [
{
"line": 4,
"column": 7
}
]
}
]
}
执行此查询时
query {
temperatureStatistics {
min
max
}
}
更新 3
改变后
temperature_statistics = graphene.Field(Temperature, before=graphene.String(), after=graphene.String())
至
temperature_statistics = graphene.Field(RangeType, before=graphene.String(), after=graphene.String())
Graphql 现在给我这个错误
{
"errors": [
{
"message": "Cannot resolve keyword 'temperature' into field. Choices are: id, timestamp, value",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"temperatureStatistics"
]
}
],
"data": {
"temperatureStatistics": null
}
}
执行此查询时
query {
temperatureStatistics {
min
max
}
}
还有:
Graphql 给我这个错误
{
"errors": [
{
"message": "Cannot resolve keyword 'created_at' into field. Choices are: id, timestamp, value",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"temperatureStatistics"
]
}
],
"data": {
"temperatureStatistics": null
}
}
执行此查询时
query {
temperatureStatistics(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00")) {
min
max
}
}
更新 4
最后一个错误是因为我在 Django 查询中使用 'temperature' 而不是 'value'。现在可以使用了。
您可以使用 min 和 max 定义一个新类型,然后像这样将其添加到您的查询中:
class RangeType(graphene.ObjectType):
min = graphene.String()
max = graphene.String()
class Query(graphene.ObjectType):
temperature_statistics = graphene.Field(
RangeType, before=graphene.String(), after=graphene.String()
)
def resolve_temperature_statistics(self, info, before=None, after=None):
range_type = RangeType()
range_type.min = # query to get min value
range_type.max = # query to get max value
return range_type
调用查询应该是一样的。
我正在尝试将 graphql 与 python 结合使用来检索某个时间范围内的最低和最高温度。
温度 table 有 2 列:时间戳和值。
我的models.py是:
from django.db import models
class Temperature(models.Model):
timestamp = models.DateTimeField(auto_now=True)
value = models.FloatField()
def __str__(self):
return f"the value:time is {self.value}:{self.timestamp}"
和schema.py是:
class Query(graphene.ObjectType):
temperature_statistics = graphene.Field(Temperature)
def resolve_temperature_statistics(self, info, **kwargs):
before = kwargs.get("before")
after = kwargs.get("after")
return models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before)
查询 return 一个时间跨度内的最低和最高温度,应该是这样的:
query {
temperatureStatistics(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00") {
min
max
}
}
我不知道如何实现它的最小和最大部分。
因为在 graphql 查询中使用了最小值和最大值,我不能只从解析器中 return 最小值和最大值,例如,如果查询是这样写的,
query {
temperatureMax(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00")
}
我必须想办法让 graphql 完成这项工作。
回应@Ahtisham 的评论。这是我如何在没有类型的情况下实现 currentTemperature。
schema.py
import graphene
from graphene_django import DjangoObjectType
from temperature import models
class Temperature(DjangoObjectType):
class Meta:
model = models.Temperature
class Query(graphene.ObjectType):
current_temperature = graphene.Field(Temperature)
def resolve_current_temperature(self, info, **kwargs):
return models.Temperature.objects.last()
schema = graphene.Schema(query=Query)
models.py
from django.db import models
class Temperature(models.Model):
timestamp = models.DateTimeField(auto_now=True)
value = models.FloatField()
这在使用此 graphql 查询查询时有效:
query {
currentTemperature {
timestamp
value
}
}
更新 2
我已经根据@Ahtisham 的回答更新了我的 schema.py,现在将其作为我的 schema.py:
import graphene
from graphene_django import DjangoObjectType
from django.db.models import Max, Min
from temperature import models
class Temperature(DjangoObjectType):
class Meta:
model = models.Temperature
class RangeType(graphene.ObjectType):
min = graphene.String()
max = graphene.String()
class Query(graphene.ObjectType):
current_temperature = graphene.Field(Temperature, id=graphene.Int())
temperature_statistics = graphene.Field(Temperature, before=graphene.String(), after=graphene.String())
def resolve_current_temperature(self, info, **kwargs):
return models.Temperature.objects.latest('timestamp')
def resolve_temperature_statistics(self, info, before=None, after=None):
range_type = RangeType()
if before and after is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__gte=after, created_at__lte=before).aggregate(Max('temperature'))
return range_type
elif before is None and after is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__gte=after).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__gte=after).aggregate(Max('temperature'))
return range_type
elif after is None and before is not None:
range_type.min_ = models.Temperature.objects.filter(created_at__lte=before).aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.filter(created_at__lte=before).aggregate(Max('temperature'))
return range_type
else:
range_type.min_ = models.Temperature.objects.aggregate(Min('temperature'))
range_type.max_ = models.Temperature.objects.aggregate(Max('temperature'))
return range_type
schema = graphene.Schema(query=Query)
Graphql 给我这个错误
{
"errors": [
{
"message": "Cannot query field \"min_\" on type \"Temperature\".",
"locations": [
{
"line": 3,
"column": 7
}
]
},
{
"message": "Cannot query field \"max_\" on type \"Temperature\".",
"locations": [
{
"line": 4,
"column": 7
}
]
}
]
}
执行此查询时
query {
temperatureStatistics {
min
max
}
}
更新 3
改变后
temperature_statistics = graphene.Field(Temperature, before=graphene.String(), after=graphene.String())
至
temperature_statistics = graphene.Field(RangeType, before=graphene.String(), after=graphene.String())
Graphql 现在给我这个错误
{
"errors": [
{
"message": "Cannot resolve keyword 'temperature' into field. Choices are: id, timestamp, value",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"temperatureStatistics"
]
}
],
"data": {
"temperatureStatistics": null
}
}
执行此查询时
query {
temperatureStatistics {
min
max
}
}
还有:
Graphql 给我这个错误
{
"errors": [
{
"message": "Cannot resolve keyword 'created_at' into field. Choices are: id, timestamp, value",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"temperatureStatistics"
]
}
],
"data": {
"temperatureStatistics": null
}
}
执行此查询时
query {
temperatureStatistics(after: "2020-12-06T12:00:00+00:00", before: "2020-12-07T12:00:00+00:00")) {
min
max
}
}
更新 4
最后一个错误是因为我在 Django 查询中使用 'temperature' 而不是 'value'。现在可以使用了。
您可以使用 min 和 max 定义一个新类型,然后像这样将其添加到您的查询中:
class RangeType(graphene.ObjectType):
min = graphene.String()
max = graphene.String()
class Query(graphene.ObjectType):
temperature_statistics = graphene.Field(
RangeType, before=graphene.String(), after=graphene.String()
)
def resolve_temperature_statistics(self, info, before=None, after=None):
range_type = RangeType()
range_type.min = # query to get min value
range_type.max = # query to get max value
return range_type
调用查询应该是一样的。