2011-06-06 6 views
1

J'ai besoin de mettre à jour plusieurs documents intégrés dans mongo en utilisant PHP. Ma mise en page ressemble à ceci:Mise à jour de plusieurs documents intégrés dans mongoDB

{ 
    _id: id, 
    visits : { 
     visitID: 12 
     categories: [{ 
       catagory_id: 1, 
       name: somename, 
       count: 11, 
       duration: 122 
       }, 
       { 
       catagory_id: 1, 
       name: some other name, 
       count: 11, 
       duration: 122 
       }, 
       { 
       catagory_id: 2, 
       name: yet another name, 
       count: 11, 
       duration: 122 
       }] 
    } 
} 

Le document peut aussi avoir plus d'une visite.

Maintenant je veux mettre à jour 2 catégories, une avec id=1 et name=somename et l'autre avec id=1 et name=some_new_name. Les deux devraient inclure "compte" de 1 et "durée" de 45.

Le premier document existe, mais le second ne le fait pas.

Im pensée d'avoir une fonction comme ceci:

function updateCategory($id, $visitID,$category_name,$category_id) { 

    $this->profiles->update(
      array(
       '_id' => $id, 
       'visits.visitID' => $visitID, 
       'visits.categories.name' => $category_name, 
       'visits.categories.id' => $category_id, 
      ), 
      array(
       '$inc' => array(
          'visits.categories.$.count' => 1, 
          'visits.categories.$.duration' =>45, 
         ), 
      ), 
      array("upsert" => true) 
    ); 
} 

Mais avec ce que je dois appeler la fonction pour chaque catégorie, je vais mettre à jour. Y a-t-il un moyen de le faire en un seul appel?

EDIT:

Changé la mise en page un peu et fait des « catégories » un objet au lieu de tableau. Puis utilisé une combinaison de "category_id" et "category_name" comme nom de propriété. Comme:

categories: { 
       1_somename : { 
        count: 11, 
        duration: 122 
       }, 
       1_some other name : { 
        count: 11, 
        duration: 122 
       }, 
       2_yet another name : { 
        count: 11, 
        duration: 122 
       }, 
} 

Puis, avec upsert et quelque chose comme

$inc: { 
"visits.$.categories.1_somename.d": 100, 
"visits.$.categories.2_yet another name.c": 1 
} 

je peux mettre à jour plusieurs "objets" à la fois ..

+0

Semble qu'il ne mettra à jour qu'une seule sous-documentation car plusieurs se réfèrent au document racine .... hmmm – sunebrodersen

Répondre

1

MongoDB tableaux qui ne supportent pas actuellement plusieurs niveaux de mise à jour en profondeur (jira) Le code suivant ne fonctionnera pas:

'$inc' =>  array( 
    'visits.categories.$.count' => 1, 
    'visits.categories.$.duration' => 123, 
), 

Donc il y a des solutions autour de cette:

1.Chargez Document => Mise à jour => save (questions possibles)
accès concurrentiel 2.Reorganize votre structure de documents comme celui-ci (et mise à jour à l'aide d'un opérateur de position):

{ 
    _id: id, 
    visits : [{ 
     visitID: 12 
    }], 
    categories: [{ 
       catagory_id: 1, 
       name: somename, 
       count: 11, 
       duration: 122, 
       visitID: 12 
       }] 
    } 
} 

3.Attendu pour la prise en charge de multiples opérateurs positionnels (planification dans la version 2.1 de mongodb).
4. Réorganisez la structure de vos documents d'une autre manière, afin d'éviter l'imbrication de plusieurs tableaux de niveaux.

+0

merci pour la réponse. Je préférerais éviter la lecture supplémentaire, donc à la place j'ai changé la disposition un peu alors les catégories sont maintenant un objet au lieu de tableau - voir éditer dans le message original. – sunebrodersen

+0

@sunebrodersen: De rien. Sympa, ça va marcher. –

Questions connexes