0

Как это должно быть написано в MongoDB?Перевести с SQL на mongo

SELECT field1, field2, product, COUNT(product) as counter 
FROM table 
GROUP BY product 
HAVING counter > 0 

Я пробовал со следующим, что почти копия из руководства Doctrine.

$query = $this->createQueryBuilder('AcmeBundle:Product') 
    ->group(array('product'), array('count' => 0)) 
    ->reduce('function (obj, prev) { prev.count++; }') 
    ->field('product, field1, field2, count') 
; 

Это только дает мне 1 элемент "count = 21", который, кажется, взял все продукты и посчитал их вместе.

+0

Не могли бы вы включить образец того, как выглядят ваши документы MongoDB и каков ваш ожидаемый результат, а не только SQL, который вы хотите перевести? – wdberkeley

ответ

0

Как и многие реализации ODM, ядро ​​доктрины (часть обтекания mongodDB) построено «поверх» основного встроенного интерфейса драйвера для MongoDB. Это позволяет подвергать эти объекты драйверов, чтобы вы могли реализовать собственные методы MongoDB для выполнения своих запросов.

Я говорю об этом, как лучший вариант для вашего запроса - aggregation framework of MongoDB. Это высокопроизводительная реализация в собственном коде на сервере, поэтому не полагается на интерпретацию JavaScript для методов типа «уменьшить», как это реализовано другими методами. Вообще говоря, DSL плохо отображает менеджеров, которые пытаются быть «всеми вещами» и, следовательно, генерировать SQL. Концепции совершенно разные и, следовательно, оптимальны.

Как оказалось, существует класс оболочки Collection, который вы можете использовать, не вдаваясь прямо в собственный драйвер. У этого есть собственный метод обертки метода .aggregate(). Отсутствие информации о том, как получить доступ к этому объекту, но вы можете проследить его по ссылке original commit.

Но получить базовый объект драйвера довольно прост:

$mongoCollection = $dm->getConnection()->getMongo() 
    ->selectCollection('collectionName'); 

$result = $mongoCollection->aggregate(
    array(
     array('$group' => array(
      '_id' => array( 
       'field1' => '$field1', 
       'field2' => '$field2', 
       'product' => '$product' 
      ), 
      'counter' => array('$sum' => 1) 
     )), 
     array('$match' => array( 
      'counter' => array('$gt' => 0) 
     )), 
     array('$project' => array( 
      'field1' => '$_id.field1', 
      'field2' => '$_id.field2, 
      'product' => '$_id.product', 
      'counter' => 1 
     )) 
    ) 
); 

Это использует оператор в $group трубопровода, чтобы сделать фактическое «группировку» через _id ключ указанного. Это может быть «составной ключ», как в этом случае, поэтому все поля берутся в совокупности. Любые поля, которые вы не хотите «группировать по», используются здесь с операторами группировки, такими как $sum, который поставляется со статическим значением 1 для представления «подсчета» совпадений.

Если вы хотите просто «группировать по» значениям поля «продукт», то другие поля в вашем результате также должны быть под grouping operator. Может быть что-то вроде $first:

$result = $mongoCollection->aggregate(
    array(
     array('$group' => array(
      '_id' => '$product', 
      'field1' => array('$first' => '$field1'), 
      'field2' => array('$first' => '$field2'), 
      'counter' => array('$sum' => 1) 
     )), 
     array('$match' => array( 
      'counter' => array('$gt' => 0) 
     )), 
     array('$project' => array(
      '_id' => 0, 
      'product' => '$_id', 
      'field1' => 1, 
      'field2' => 1, 
      'counter' => 1 
     )) 
    ) 
); 

Но любые поля, которые вы хотите должны быть предметом "grouping operator" или являются частью «группы по» заявления. То же самое верно для SQL.

Другие «конвейерные» этапы здесь в основном $match, которые выполняются «после группировки», чтобы иметь тот же эффект, что и предложение «HAVING», и, наконец, $project, который просто очищает выход, чтобы иметь желаемое поле вместо добавления в нужный код _id («группа по»).

Вот как вы делаете агрегацию в MongoDB.

Дополнительную информацию об общих операциях SQL см. В статье SQL to Aggregation Mapping Chart в основной документации.

Смежные вопросы