Django HStore Field 和 JSON Field

326 阅读2分钟

HStore Field

HStore Field 是postgresql在Django中提供的一个field,可以存储key(must string)-value(strings or nulls)形式的数据,在python中体现为dict和None。

要使用该Field,需要设置:

  1. Add 'django.contrib.postgres' in your INSTALLED_APPS.
  2. Setup the hstore extension in PostgreSQL.
  • 支持一些自定义的查询方法,例如:

    •  >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
      >>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
      >>> Dog.objects.filter(data__breed='collie')
      <QuerySet [<Dog: Meg>]>
      
    • 还可以连接一些其他的key查询方法:

      • 查询key如果不是像contains这样的查询关键字的话,都会被当做一个key查询,不会有任何错误抛出

      •  >>> Dog.objects.filter(data__breed__contains='l')
        <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
        

JSON Field

PostgreSql 提供两个native JSON based data types: json and jsonb, 前者存储的是string格式,后者是真正的json格式,所以对于前者的查询必须是在线解析的,后者则是行为类似json的可以index的查询,后者就是会在写入的时候会有额外的开销。JSONField使用的是jsonb。

存储JSON格式的数据,在python中体现为dictionaries, lists, strings, numbers, booleans and None。

encoder参数:提供自定义序列化,来支持那些不能被标准JSONEncoder所序列化的类型

default参数: 必须提供的是callable!

  • 查询方法

    •  >>> Dog.objects.create(name='Rufus', data={
      ...    'breed': 'labrador',
      ...    'owner': {
      ...        'name': 'Bob',
      ...        'other_pets': [{
      ...            'name': 'Fishy',
      ...        }],
      ...    },
      ... })
      >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': None})
      >>> Dog.objects.filter(data__breed='collie')
      <QuerySet [<Dog: Meg>]>
      
  • 多个Key可以chain query
  •  >>> Dog.objects.filter(data__owner__name='Bob')
    <QuerySet [<Dog: Rufus>]>
    
  • 如果Key是一个integer, 会被当做数组的一个index查询
  •  >>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
    <QuerySet [<Dog: Rufus>]>
    
  • 查询 null, 用None

  •  >>> Dog.objects.filter(data__owner=None)
    <QuerySet [<Dog: Meg>]>
    

两者的区别优缺点

  • HStore是第一个出现在Psql中的k-v形式的数据格式,变相的支持了NOSQL,但限制相对很大
  • JsonField使用的是jsonb数据类型,是最新的一种底层就支持JSON格式且内置查询方法的格式,比如支持嵌套,数组等类型,这是HStore比不了的

所以综上,在没有特殊情况下,毫无疑问是选择使用JSONField的