2013-07-22 11 views
7

Le pilote Mongo de PHP n'a pas de fonction renameCommand. There is reference pour ce faire via la base de données d'administration. Mais il semble que des versions plus récentes du pilote Mongo ne vous permettent pas simplement "d'utiliser" la base de données d'administration si vous n'avez pas de privilèges de connexion sur cette base de données. Donc, cette méthode ne fonctionne plus. J'ai aussi lu que cela ne fonctionne pas dans les environnements partagés, bien que ce ne soit pas une préoccupation pour moi actuellement.Renommer une collection Mongo en PHP

L'autre suggestion que les gens semblent avoir est d'itérer à travers la collection "from" et d'insérer dans la collection "to". Avec le bon WriteConcern (fire and forget) cela pourrait être assez rapide. Mais cela signifie tout de même que chaque enregistrement sur le réseau sera transféré dans le processus PHP, puis transféré de nouveau sur le réseau dans la base de données.

Je veux idéalement un moyen de le faire tous côté serveur. Un peu comme un INSERT INTO ... SELECT ... dans SQL. De cette façon, il est rapide, efficace sur le réseau et faible charge sur PHP.

Répondre

0

Mises à jour:

  • supprimé mon ancienne map/reduce méthode depuis que j'ai découvert (et Sammaye fait remarquer) que cela modifie la structure
  • fait ma version exec secondaire depuis que j'ai découvert comment faites le avec renameCollection.

Je crois que j'ai trouvé une solution. Il semble que certaines versions du pilote PHP seront authentiques par rapport à la base de données d'administration, même si cela n'est pas nécessaire. Mais il y a a workaround où le paramètre de connexion authSource est utilisé pour modifier ce comportement afin qu'il ne soit pas auth en fonction de la base de données d'administration mais de la base de données de votre choix. Alors maintenant, ma fonction renameCollection est juste un wrapper autour de la commande renameCollection.

La clé consiste à ajouter authSource lors de la connexion. Dans le code ci-dessous $ _ENV ['MONGO_URI'] contient ma chaîne de connexion et default_database_name() renvoie le nom de la base de données que je veux authentifier.

$class = 'MongoClient'; 
if(!class_exists($class)) $class = 'Mongo'; 
$db_server = new $class($_ENV['MONGO_URI'].'?authSource='.default_database_name()); 

Voici ma version plus ancienne qui a utilisé eval qui devrait également fonctionner même si certains environnements ne vous permettent pas de eval (MongoLab vous donne une configuration estropié à moins que vous avez un système dédié). Mais si vous travaillez dans un environnement fragmenté, cela semble être une solution raisonnable.

function renameCollection($old_name, $new_name) { 
    db()->$new_name->drop(); 
    $copy = "function() {db.$old_name.find().forEach(function(d) {db.$new_name.insert(d)})}"; 
    db()->execute($copy); 
    db()->$old_name->drop(); 
} 
+0

MR va changer la structure du document entre les deux collections, et vous devriez être en mesure de « utiliser » la base de données admin si vous avez le droit auth – Sammaye

+0

Oui, je me suis aperçu que je posté prématurément que je ne l'ai pas remarqué le changement de structure. J'essaie actuellement de comprendre comment je peux faire une carte/réduire sans réduire la partie. –

+0

Ce n'est pas un problème avec la réduction mais fondamentalement, en interne, comment MongoDB forme les documents résultants et les écrit. En fait, vous ne devriez jamais exécuter la réduction puisque vous ne devez retourner qu'une clé par document et que MongoDBs ne s'exécute pas dans ce cas. – Sammaye

0

Je viens de tester cela, il fonctionne comme prévu (http://docs.mongodb.org/manual/reference/command/renameCollection/):

$mongo->admin->command(array('renameCollection'=>'ns.user','to'=>'ns.e')); 

Voilà comment vous renommez un collection unsharded. Un problème avec MR est qu'il va changer la forme de la sortie de la collection originale. En tant que tel, il n'est pas très bon pour copier une collection. Vous feriez mieux de le copier manuellement si votre collection est partagée. Comme note ajoutée j'ai mis à jour vers 1.4.2 (qui pour une raison quelconque sort du canal pecl dans phpinfo() comme 1.4.3dev :S) et cela fonctionne toujours.

+0

C'est ce que je faisais auparavant. Mais depuis que j'ai mis à jour le pilote mongo (à 1.4.1) il a cessé de se plaindre de l'authentification. J'ai encore une autre machine sur l'ancien pilote mongo et cela fonctionne encore, donc je sais que ce n'est pas un problème d'autorisation de base de données. –

+0

@EricAnderson Je suis sur 1.4.2 et je n'ai pas ce problème – Sammaye

+0

Peut-être 1.4.1 spécifique. J'ai trouvé un problème lié à cela qui fournit une solution de contournement en utilisant authSource à l'adresse https://jira.mongodb.org/browse/PHP-782. Alors maintenant, revenons à simplement utiliser renameCollection. Merci de m'avoir aidé à comprendre tout cela. –

-1

vous pouvez l'utiliser. L'indicateur "dropTarget" est true, puis supprime la base de données existante.

$mongo = new MongoClient('_MONGODB_HOST_URL_'); 
    $query = array("renameCollection" => "Database.OldName", "to" => "Database.NewName", "dropTarget" => "true"); 

    $mongo->admin->command($query); 
+0

Cela ne résout pas le problème. Le problème est que la commande renameCommand ne fonctionne pas toujours en fonction des informations d'identification et de la version du pilote Mongo. L'exécution de la commande avec dropTarget était ce que j'essayais de faire. Cela ne fonctionne pas toujours si vous n'avez pas de privilèges sur la base de données d'administration ou si vous utilisez certaines versions du pilote PHP mongo. –

Questions connexes