Проекция построителя запросов доктрины mongodb с пронумерованными индексами

Мне нужно ограничить объем данных, возвращаемых запросом доктрины mongoDB. Я мог бы использовать select для проецирования на простые поля или даже простые встроенные поля массива, такие как normalizedData.ean. Это работает отлично.

Однако у меня есть необходимые данные в форме, подобной следующей:

"values" : [
    {
        "_id" : ObjectId("59cbd73d83218bf7668b468d"),
        "attribute" : NumberLong("1"),
        "entity" : DBRef("pim_catalog_product", ObjectId("59148d2583218bf7508c1199"), "akeneo_pim"),
        "varchar" : "10011060"
    },
    {
        "_id" : ObjectId("59cbd73d83218bf7668b468e"),
        "attribute" : NumberLong("207"),
        "entity" : DBRef("pim_catalog_product", ObjectId("59148d2583218bf7508c1199"), "akeneo_pim"),
        "varchar" : "PRO70"
    },
    {
        "_id" : ObjectId("59cbd73d83218bf7668b468f"),
        "attribute" : NumberLong("110"),
        "entity" : DBRef("pim_catalog_product", ObjectId("59148d2583218bf7508c1199"), "akeneo_pim"),
        "option" : NumberLong("1890")
    }
]

Между прочим, фреймворк Akeneo PIM.

Итак, проблема здесь в том, что "values" индексируются не с помощью уникальных идентификаторов, которые я мог бы использовать, а с помощью пронумерованных индексов. Я заранее знаю номер "attribute", поэтому я могу запросить его.

Итак, что я ищу, так это построитель запросов к базе данных Doctrin Mongo DB, способный возвращать только те сущности, которые на самом деле содержат значения с номерами атрибутов 110 и 207, плюс я хочу возвращать только данные в пределах этих значений.

У меня есть рабочий построитель запросов, который работает с уникальными (строковыми) индексами:

$query = $productRepository->createQueryBuilder()
        ->hydrate(false)
        ->select(array('normalizedData.sku'))
        ->field('_id')->in($entityIds)
        ->limit($limit)
        ->skip($offset);

РЕДАКТИРОВАТЬ: теперь я нашел способ запросить эти "values", но я не могу проецировать более одного атрибута с помощью этого запроса:

$qb = $productRepository->createQueryBuilder();
$query = $qb
    ->hydrate(false)
    ->select(array('normalizedData.sku'))
    ->selectElemMatch(
        'values',
        $qb->expr()->field('attribute')->in(array(117, 110))->addAnd(
            $qb->expr()->field('locale')->in(array('it_IT', 'de_DE'))
        ))
    ->field('_id')->in($entityIds)
    ->field('values')->elemMatch($qb->expr()->field('attribute')->in(array(117, 110)))
    ->limit($limit)
    ->skip($offset);

Здесь я пытаюсь получить оба атрибута (117 и 110), но получаю только один. Кроме того, я получаю некоторые результаты, в которых отсутствует ни один из атрибутов, хотя я предполагал, что отфильтровал атрибуты с ->field('values')->elemMatch($qb->expr()->field('attribute')->in(array(117, 110))).

Очевидно, что есть еще некоторые основы, которые мне нужно понять о mongoDB. Любая помощь будет принята с благодарностью.

Как мне получить только те объекты, которые имеют атрибут 117 и/или 110 в своей коллекции «значений», а также получить только данные этих атрибутов?

Примечание. Один и тот же идентификатор атрибута можно использовать несколько раз для разных языков. Я хотел бы также иметь возможность ограничить результат указанными языками.


person Micha    schedule 16.01.2018    source источник


Ответы (1)


Пробовали ли вы доктрину Построитель агрегации? Это может быть началом решения, особенно с функцией unwind, которая может сгладить ваши значения и упростить построение запроса.

https://doctrine-mongodb-odm.readthedocs.io/en/latest/reference/aggregation-builder.html

Надеюсь, это поможет вам!

person Jeremy Jumeau    schedule 12.02.2018