对hstore或json数据进行Django数值比较?

2024-05-15 13:40:30 发布

您现在位置:Python中文网/ 问答频道 /正文

是否可以通过将hstore值强制转换为int或{}来过滤查询集?在

我遇到了一个问题,我们需要向现有的数据模型添加更健壮的查询。数据模型使用HStoreField来存储大多数建筑数据,我们需要能够根据它们进行查询/过滤,并且一些值需要被视为数值。在

但是,由于这些值被视为字符串,因此逐个字符地比较它们会导致错误的查询。例如,'700' > '1000'。在

因此,如果我想查询sqft值在700和1000之间的所有项目,我会得到零结果,尽管我可以清楚地看到有数百个项目的值在这个范围内。如果我只查询sqft value>;=700的项目,我只得到sqft值以7、8或9开头的结果。在

我还尝试使用django-pgjson中的JsonField来测试这一点(因为我们还没有使用django1.9),但它似乎也有相同的问题。在

设置

Django==1.8.9
django-pgjson==0.3.1 (for jsonfield functionality)
Postgres==9.4.7

模型.py

^{pr2}$

示例数据

这是hstore字段上的一些数据的示例。在

address1: ...
address2: ...
city: ...
state: ...
zipcode: ...
data: {
    'year_built': '1995',
    'building_type': 'residential',
    'building_subtype': 'single-family',
    'bedrooms': '2',
    'bathrooms': '1',
    'total_sqft': '958',
}

返回错误结果的示例查询

queryset = Building.objects.filter(data__total_sqft__gte=700)

我尝试过使用annotate特性,看看是否可以强制将其强制转换为数值,但我没有任何运气让它起作用。我总是收到一个错误,说我要查询的字段不存在。这是我在别处找到的一个例子,但似乎行不通。在

queryset = Building.objects.all().annotate(
    sqft=RawSQL("((data->>total_sqft)::numeric)")
).filter(sqft__gte=700)

从而导致此错误:

FieldError: Cannot resolve keyword 'sqft' into field. Choices are: address1, address2, city, state, zipcode, data

使这个设置更加复杂的一点是,我们动态地构建查询并使用Q()对象和/或它们一起使用。在

所以,尝试这样做,给定一个键、值和运算符类型(gtelteiexact):

queryset.annotate(**{key: RawSQL("((%data->>%s)::numeric)", (key,)})
queries.append(Q(**{'{}__{}'.format(key, operator): value})
queries.filter(reduce(operator.and_, queries)

不过,我很乐意让第一个查询正常工作,而不需要动态地构建它们。在

我曾考虑过必须用显式定义的字段为建筑数据创建单独的模型的可能性,但是datahs存储中有600多个键值对。似乎将其转换为具体的数据模型对于设置和维护来说都是一场噩梦。在


Tags: 数据项目key示例data错误hstore数据模型