Django: фильтр JSONField с несколькими вложенными массивами

У меня есть JSONField, называется metadata на моей модели в Джанго.

Данные в этих полях могут выглядеть примерно так

{
    "vis": {
        "plots": [
            // some objects here
            {
                "id": 1,
                "x": "foo",
                "y": "bar",
                "externalData": [
                    // some objects here
                    {
                        "x": "fa",
                        "y": "so",
                        "source": {
                            "name": "FINDME",
                            "location": "some other address"
                        }
                    },
                    // some more objects here
                ]
            },
            // some more objects here
        ],
        "somethingElse": []
    },
    "moreStuff": {}
}

Я хочу иметь возможность фильтровать модели, которые имеют "name": "FINDME" в externalData объект (с любым индексом), внутри plots объект (также с любым индексом).

Я изначально пробовал

MyModel.objects.filter(metadata__vis__plots__externalData__source__name='FINDME')

Не хорошо. Потом я попробовал

MyModel.objects.filter(metadata__vis__plots__externalData__source__contains={'name':'FINDME'})

Не хорошо. Потом я попробовал

MyModel.objects.filter(metadata__vis__plots__externalData__contains=[{'source': {'name':'FINDME'}}])

Все еще не повезло. Наконец я попробовал

MyModel.objects.filter(metadata__vis__plots__contains=[{'externalData':[{'source': {'name': 'FINDME'}}]}])

По-прежнему нет хитов.

Очевидно, я делаю все это неправильно.

Есть идеи?

РЕДАКТИРОВАТЬ: я добавил несколько комментариев в JSON, чтобы прояснить, что у меня не только один объект в каждом из моих массивов. Я пытаюсь найти "сюжет" по произвольному индексу и "externalData" по произвольному индексу, который содержит "source": {"name": "FINDME"},

1 ответ

Поскольку "plots" является индексом, вам необходимо представить этот индекс в вашем содержимом. Структура вашего содержимого должна соответствовать JSON, начиная с первого массива. Каждый уровень массива в вашем JSON должен быть представлен в содержащем =

Это проще показать, чем сказать. Как это:

MyModel.objects.filter(
     metadata__vis__plots__contains=[{'externalData': [{'source': {'name': 'FINDME'}}]}]
)

У вас есть список dicts внутри вашего JSON, поэтому вам нужно добавить индекс к вашему запросу

MyModel.objects.filter(
         metadata__vis__plots__0__externalData__contains=[{"source": {"name": "FINDME"}}])
#                           ^^^^^
Другие вопросы по тегам