#django #postgresql #jsonb
#django #postgresql #jsonb
Вопрос:
У меня есть Django data
JSONField со следующими данными в
{
"title": "Some Title",
"projects": [
{"name": "Project 1", "score": "5"},
{"name": "Project 2", "score": "10"},
{"name": "Project 3", "score": "2"},
]
}
И мне нужно фильтровать строки по оценкам проекта (числовой тип), т.е. where project -> score <= 5
Django ORM предоставляет основы фильтрации и работы с полем Postgres JSONB. То есть я могу сделать
Model.objects.filter(data__title="Some Title")
Но это не так просто при наличии списка элементов в столбце JSON, т. Е. Я не могу сделать
Model.objects.filter(data__projects__score__lte=5)
Only way I can reach the `score` in Django ORM is to use the array index, i.e.
Model.objects.filter(data__projects__0__score__lte=5)
Но сейчас это не работает, меня интересуют все элементы в этом списке, которых может быть сколько угодно
Где я сейчас нахожусь:
Я присоединил этот список к набору запросов как jsonb_array_elements
queryset.query.join(join=join_cfg)
Который добавил следующий sql к ЗАПРОСУ
LEFT JOIN LATERAL jsonb_array_elements("my_table"."data" -> 'projects') projects ON TRUE
Теперь, в необработанном SQL, я могу сделать что-то вроде этого, чтобы отфильтровать этот список
WHERE (projects->>'score')::numeric < 5
Проблема в том, что я не могу заставить это хорошо работать с Django ORM
В настоящее время я добавляю это WHERE
предложение, используя queryset.extra()
queryset = queryset.extra(where=where_clause)
Проблема с этим заключается в том, что при использовании .extra()
предложение WHERE редактируется AND
в конце запроса, что приводит к неожиданным результатам в сочетании с другими фильтрами, выполняемыми с использованием Q
объектов Django.
Т.е. Последнее сгенерированное предложение WHERE выглядит следующим образом:
WHERE condition1 AND (condition2 OR condition3) AND MY_CUSTOM_WHERE_CONDITION
// but what I need is
WHERE condition1 AND (condition2 OR condition3 OR MY_CUSTOM_WHERE_CONDITION)
В идеале это пользовательское условие должно быть добавлено вместе с Q
объектом, т.е.
query_filters |= Q(projects__score__lte=5)
Но поскольку projects
столбец является пользовательским соединением, я понимаю Cannot resolve keyword 'projects' into field.
, что не могу использовать django ORM для фильтрации так же, как я фильтрую title
в начале этого сообщения
Я думаю, что это пользовательское соединение должно быть каким-то образом аннотировано, а затем использовать Q
объект в этом аннотированном столбце, но я не могу заставить это работать.
Я пробовал, дополнительный выбор, аннотации с помощью RawSql, FilteredRelation, все..
Любая помощь приветствуется. Спасибо