2011-05-24 12 views
2

J'utilise Doctrine ODM avec mongoDB.Doctrine ODM/MongoDB: dans les requêtes AND

Je suis en train de faire des requêtes telles que:

$queryBuilder->field('array_field')->in('even_value_1', 'event_value_2'); 
$queryBuilder->field('array_field')->in('odd_value_1', 'odd_value_2'); 

L'idée est de sélectionner tous les documents qui ont dans leur

array_field(event_value_1 OR event_value_2) AND (odd_value_1 OR odd_value_2) 

Avec la syntaxe que je utilise, je reçois les documents qui ont

event_value_1 OR event_value_2 OR odd_value_1 OR odd_value_2 

Des idées sur la façon de procéder ou si c'est possible?

Répondre

3

Il semble que l'opérateur $ et n'est pas disponible actuellement dans MongoDB. Le $ et l'opérateur est en 1.9.1 (version instable)

Voici le billet pour la demande de fonctionnalité: https://jira.mongodb.org/browse/SERVER-1089

Actuellement (1.8.x) la seule solution semble utiliser plusieurs « $ ou » statments comme:

even_value_1 AND odd_value_1 
OR even_value_1 AND odd_value_2 
OR even_value_2 AND odd_value_1 
OR event_value_2 AND odd_value_2 

EDIT: Voici un code pour aider les futurs utilisateurs

d'abord, nous avons besoin d'une fonction pour transformer notre

array_field(event_value_1 OR event_value_2) AND (odd_value_1 OR odd_value_2) 

à

even_value_1 AND odd_value_1 
OR even_value_1 AND odd_value_2 
OR even_value_2 AND odd_value_1 
OR event_value_2 AND odd_value_2 

Voici les fonctions nécessaires

/** 
* $pArray for our example should be like array(array(event_value_1, 
*     event_value_2),array(odd_value_1, odd_value_2)) 
*/ 
function transform_and_group_of_or_to_or_group_of_and ($pArray) 
{ 
    //Make sure we have sequential numerical indexes 
    sort($pArray); 

    $maxIndices = array(); 
    foreach ($pArray as $key=>&$values){ 
     //Make sure we have sequential numerical indexes 
     sort($values); 

     $maxIndices[$key] = count($values)-1; 
     $arIndices[$key] = 0; 
    } 

    $groupCount = count($pArray); 
    $groupOfAnd = array(); 

    do { 
     $newGroup = array(); 
     for ($i=0; $i<$groupCount; $i++){ 
      $indice = $arIndices[$i]; 
      $sousTab = $pArray[$i]; 
      $newGroup[] = $sousTab[$indice]; 
     } 
     $groupOfAnd[] = $newGroup; 
    } while(increment_numbers($arIndices, $maxIndices)); 

    return $groupOfAnd; 
} 

function increment_numbers(& $arIndices, $maxIndices){ 
    //Raise the last indice 
    $arIndices[count($arIndices)-1]++; 

    $check = true; 
    for ($i=count($arIndices)-1; (($i>=0) && ($check === true)); $i--){ 
     if ($arIndices[$i] > $maxIndices[$i]){ 
      if ($i > 0){ 
       $arIndices[$i-1]++;//increment the upper indice element 
      } else { 
       return 0; 
      } 
      $arIndices[$i] = 0; 
      $check=true; 
     }else{ 
      $check = false; 
     } 
    } 
    return true; 
} 

Pour la partie Doctrine ODM:

if (count($arGroupedCritere)) { 
     $arGroupedCritere = transform_and_group_of_or_to_or_group_of_and($arGroupedCritere); 
      foreach($arGroupedCritere as $arCritere) { 
       $queryBuilder->addOr($queryBuilder->expr()->field('_criteres')->all($arCritere)); 
      } 
    } 

Hope this helps

Questions connexes