9

tôi chạy Django 1.9 với JSONField mới và có mô hình thử nghiệm như sau:Django lọc JSONField danh sách dicts

class Test(TimeStampedModel): 
    actions = JSONField() 

Hãy nói rằng hành động JSONField trông như thế này:

[ 
    { 
    "fixed_key_1": "foo1", 
    "fixed_key_2": { 
     "random_key_1": "bar1", 
     "random_key_2": "bar2", 
    } 
    }, 
    { 
    "fixed_key_1": "foo2", 
    "fixed_key_2": { 
     "random_key_3": "bar2", 
     "random_key_4": "bar3", 
    } 
    } 
] 

Tôi muốn có thể lọc các phím foo1 và foo2 cho mọi mục trong danh sách. Khi tôi làm:

>>> Test.objects.filter(actions__1__fixed_key_1="foo2") 

Thử nghiệm nằm trong bộ truy vấn. Nhưng khi tôi làm:

>>> Test.objects.filter(actions__0__fixed_key_1="foo2") 

Điều đó không có ý nghĩa. Tôi muốn làm điều gì đó như:

>>> Test.objects.filter(actions__values__fixed_key_1="foo2") 

Hoặc

>>> Test.objects.filter(actions__values__fixed_key_2__values__contains="bar3") 

Và có Test trong queryset.

Bất kỳ ý tưởng nào nếu điều này có thể được thực hiện và cách thực hiện?

Trả lời

2

Bạn có thể sử dụng gói django-jsonfield, tôi đoán đó là gói bạn đang sử dụng.

from jsonfield import JSONField 
class Test(TimeStampedModel): 
    actions = JSONField() 

Vì vậy, để tìm kiếm để thực hiện một tìm kiếm với một tài sản cụ thể, bạn chỉ có thể làm điều này:

def test_filter(**kwargs): 
    result = Test.objects.filter(actions__contains=kwargs) 
    return result 

Nếu bạn đang sử dụng PostgreSQL, có lẽ bạn có thể tận dụng lợi thế của PostgreSQL specific model fields.

PS: Nếu bạn đang xử lý rất nhiều cấu trúc JSON, bạn có thể cân nhắc việc sử dụng Cơ sở dữ liệu NoSQL.

+1

Tôi thực sự đã sử dụng trường mô hình cụ thể JSONField của PostgreSQL ('từ django.contrib.postgres.fields nhập JSONField').Giải pháp của bạn hoạt động khi 'your_property' được biết (' fixed_key_1' và 'fixed_key_2' trong trường hợp của tôi) nhưng làm thế nào tôi có thể làm khi tôi không biết' your_property' ('random_key_ #' trong trường hợp của tôi)? – Scentle5S

+0

Bạn nên đặt '{'fixed_key_1': 'foo2'}' của bạn, tôi đã cập nhật mã bằng hàm chung. – DhiaTN

+1

Điều tôi không biết là 'your_property'. Nó có thể là bất cứ điều gì và tôi thậm chí không quan tâm về nó, chỉ muốn biết nếu JSONField có chứa một chuỗi nhất định trong bất kỳ giá trị của nó, bất kể chiều sâu. – Scentle5S

2

Bạn có thể sử dụng tra cứu __contains cho điều này, như được ghi trong tài liệu here. Việc tra cứu vẫn sẽ giống như những gì DhiaTN đã đề xuất ở trên. Vì vậy, một cái gì đó như thế này nên làm việc:

Test.objects.filter(actions__contains={'fixed_key_1': 'foo2'}) 
15

Nếu bạn wan't để lọc dữ liệu của bạn bằng cách một trong những lĩnh vực trong mảng của bạn của dicts, bạn có thể thử truy vấn này:

Test.objects.filter(actions__contains=[{'fixed_key_1': 'foo2'}]) 

Nó sẽ liệt kê tất cả các đối tượng Test có ít nhất một đối tượng trong trường actions có chứa khóa fixed_key_1 giá trị foo2.

Ngoài ra nó nên làm việc cho tra cứu lồng nhau, ngay cả khi bạn không biết chỉ số thực tế:

Test(actions=[ 
    {'fixed_key_1': 'foo4', 'fixed_key_3': [ 
     {'key1': 'foo2'}, 
    ]} 
}).save() 

Test.objects.filter(actions__contains=[{'fixed_key_3': [{'key1': 'foo2'}]}]) 

Nói cách đơn giản, chứa sẽ bỏ qua mọi thứ khác.

Thật không may, nếu phần tử lồng nhau là đối tượng, bạn phải biết tên khóa. Tra cứu theo giá trị sẽ không hoạt động trong trường hợp đó.

Các vấn đề liên quan